diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 426cf83e2ec..f60d774937f 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,5 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:b0b1c1c89570e229b1026372a2b8989ba31495007055b8d30178b7648503eefa + digest: sha256:fc52b202aa298a50a12c64efd04fea3884d867947effe2fa85382a246c09e813 +# created: 2022-04-06T16:30:03.627422514Z diff --git a/.github/auto-label.yaml b/.github/auto-label.yaml new file mode 100644 index 00000000000..4caef688b74 --- /dev/null +++ b/.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 diff --git a/CHANGELOG.md b/CHANGELOG.md index a2fc6cc934d..fd510305ad3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +### [6.23.3](https://github.com/googleapis/java-spanner/compare/v6.23.2...v6.23.3) (2022-04-21) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.10.0 ([#1830](https://github.com/googleapis/java-spanner/issues/1830)) ([3c55eb3](https://github.com/googleapis/java-spanner/commit/3c55eb336e77ee1ddfb6c055722697f81419578c)) + + +### Documentation + +* add samples for PostgreSQL ([#1700](https://github.com/googleapis/java-spanner/issues/1700)) ([a024483](https://github.com/googleapis/java-spanner/commit/a02448388ba2415d31593a8c81b4430e2264c10c)) + ### [6.23.2](https://github.com/googleapis/java-spanner/compare/v6.23.1...v6.23.2) (2022-04-11) diff --git a/README.md b/README.md index 6a4efce693a..f64bbab1f2b 100644 --- a/README.md +++ b/README.md @@ -56,13 +56,13 @@ implementation 'com.google.cloud:google-cloud-spanner' If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner:6.23.1' +implementation 'com.google.cloud:google-cloud-spanner:6.23.2' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.23.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.23.2" ``` ## Authentication @@ -264,6 +264,10 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/ | Get Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java) | | List Databases Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java) | | List Instance Configs Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java) | +| Pg Batch Dml Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgBatchDmlSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/PgBatchDmlSample.java) | +| Pg Case Sensitivity Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java) | +| Pg Interleaved Table Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java) | +| Pg Partitioned Dml Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgPartitionedDmlSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/PgPartitionedDmlSample.java) | | Query Information Schema Database Options Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryInformationSchemaDatabaseOptionsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryInformationSchemaDatabaseOptionsSample.java) | | Query With Json Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithJsonParameterSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryWithJsonParameterSample.java) | | Query With Numeric Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithNumericParameterSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryWithNumericParameterSample.java) | diff --git a/google-cloud-spanner-bom/pom.xml b/google-cloud-spanner-bom/pom.xml index e02db2ee39e..aa6096e9e57 100644 --- a/google-cloud-spanner-bom/pom.xml +++ b/google-cloud-spanner-bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-spanner-bom - 6.23.2 + 6.23.3 pom com.google.cloud @@ -53,43 +53,43 @@ com.google.cloud google-cloud-spanner - 6.23.2 + 6.23.3 com.google.cloud google-cloud-spanner test-jar - 6.23.2 + 6.23.3 com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.23.2 + 6.23.3 com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.23.2 + 6.23.3 com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.23.2 + 6.23.3 com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.23.2 + 6.23.3 com.google.api.grpc proto-google-cloud-spanner-v1 - 6.23.2 + 6.23.3 com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.23.2 + 6.23.3 diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml index 75de5f18d17..6a002f2c23a 100644 --- a/google-cloud-spanner/pom.xml +++ b/google-cloud-spanner/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-spanner - 6.23.2 + 6.23.3 jar Google Cloud Spanner https://github.com/googleapis/java-spanner @@ -11,7 +11,7 @@ com.google.cloud google-cloud-spanner-parent - 6.23.2 + 6.23.3 google-cloud-spanner diff --git a/grpc-google-cloud-spanner-admin-database-v1/pom.xml b/grpc-google-cloud-spanner-admin-database-v1/pom.xml index 1a7f9936006..72236c470d3 100644 --- a/grpc-google-cloud-spanner-admin-database-v1/pom.xml +++ b/grpc-google-cloud-spanner-admin-database-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.23.2 + 6.23.3 grpc-google-cloud-spanner-admin-database-v1 GRPC library for grpc-google-cloud-spanner-admin-database-v1 com.google.cloud google-cloud-spanner-parent - 6.23.2 + 6.23.3 diff --git a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml index b4c27573897..f8cb84d192c 100644 --- a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml +++ b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.23.2 + 6.23.3 grpc-google-cloud-spanner-admin-instance-v1 GRPC library for grpc-google-cloud-spanner-admin-instance-v1 com.google.cloud google-cloud-spanner-parent - 6.23.2 + 6.23.3 diff --git a/grpc-google-cloud-spanner-v1/pom.xml b/grpc-google-cloud-spanner-v1/pom.xml index 5eba65762b5..05dc7686d91 100644 --- a/grpc-google-cloud-spanner-v1/pom.xml +++ b/grpc-google-cloud-spanner-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.23.2 + 6.23.3 grpc-google-cloud-spanner-v1 GRPC library for grpc-google-cloud-spanner-v1 com.google.cloud google-cloud-spanner-parent - 6.23.2 + 6.23.3 diff --git a/pom.xml b/pom.xml index be24a60623b..7706a54dc78 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-spanner-parent pom - 6.23.2 + 6.23.3 Google Cloud Spanner Parent https://github.com/googleapis/java-spanner @@ -54,7 +54,7 @@ UTF-8 github google-cloud-spanner-parent - 2.9.0 + 2.10.0 @@ -62,37 +62,37 @@ com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.23.2 + 6.23.3 com.google.api.grpc proto-google-cloud-spanner-v1 - 6.23.2 + 6.23.3 com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.23.2 + 6.23.3 com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.23.2 + 6.23.3 com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.23.2 + 6.23.3 com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.23.2 + 6.23.3 com.google.cloud google-cloud-spanner - 6.23.2 + 6.23.3 @@ -186,7 +186,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.2 + 3.4.0 html diff --git a/proto-google-cloud-spanner-admin-database-v1/pom.xml b/proto-google-cloud-spanner-admin-database-v1/pom.xml index d03afe6993d..138cad9632a 100644 --- a/proto-google-cloud-spanner-admin-database-v1/pom.xml +++ b/proto-google-cloud-spanner-admin-database-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.23.2 + 6.23.3 proto-google-cloud-spanner-admin-database-v1 PROTO library for proto-google-cloud-spanner-admin-database-v1 com.google.cloud google-cloud-spanner-parent - 6.23.2 + 6.23.3 diff --git a/proto-google-cloud-spanner-admin-instance-v1/pom.xml b/proto-google-cloud-spanner-admin-instance-v1/pom.xml index 1681603beeb..ebca30bbba0 100644 --- a/proto-google-cloud-spanner-admin-instance-v1/pom.xml +++ b/proto-google-cloud-spanner-admin-instance-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.23.2 + 6.23.3 proto-google-cloud-spanner-admin-instance-v1 PROTO library for proto-google-cloud-spanner-admin-instance-v1 com.google.cloud google-cloud-spanner-parent - 6.23.2 + 6.23.3 diff --git a/proto-google-cloud-spanner-v1/pom.xml b/proto-google-cloud-spanner-v1/pom.xml index f5d2ee02b72..17fd62d30fb 100644 --- a/proto-google-cloud-spanner-v1/pom.xml +++ b/proto-google-cloud-spanner-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-spanner-v1 - 6.23.2 + 6.23.3 proto-google-cloud-spanner-v1 PROTO library for proto-google-cloud-spanner-v1 com.google.cloud google-cloud-spanner-parent - 6.23.2 + 6.23.3 diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 85aa037c67c..beafda0b4e7 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -31,7 +31,7 @@ com.google.cloud google-cloud-spanner - 6.23.2 + 6.23.3 diff --git a/samples/snippets/src/main/java/com/example/spanner/PgBatchDmlSample.java b/samples/snippets/src/main/java/com/example/spanner/PgBatchDmlSample.java new file mode 100644 index 00000000000..6851dfd366e --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/PgBatchDmlSample.java @@ -0,0 +1,85 @@ +/* + * Copyright 2022 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. + */ + +package com.example.spanner; + +// [START spanner_postgresql_batch_dml] + +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.Statement; +import java.util.Arrays; + +class PgBatchDmlSample { + + static void batchDml() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + + batchDml(projectId, instanceId, databaseId); + } + + static void batchDml(String projectId, String instanceId, String databaseId) { + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); + + // Spanner PostgreSQL supports BatchDML statements. This will batch multiple DML statements + // into one request, which reduces the number of round trips that is needed for multiple DML + // statements. + long[] updateCounts = + client + .readWriteTransaction() + .run( + transaction -> + transaction.batchUpdate( + Arrays.asList( + Statement.newBuilder( + "INSERT INTO Singers (SingerId, FirstName, LastName) " + + "VALUES ($1, $2, $3)") + // Use 'p1' to bind to the parameter with index 1 etc. + .bind("p1") + .to(1L) + .bind("p2") + .to("Alice") + .bind("p3") + .to("Henderson") + .build(), + Statement.newBuilder( + "INSERT INTO Singers (SingerId, FirstName, LastName) " + + "VALUES ($1, $2, $3)") + // Use 'p1' to bind to the parameter with index 1 etc. + .bind("p1") + .to(2L) + .bind("p2") + .to("Bruce") + .bind("p3") + .to("Allison") + .build()))); + long totalUpdateCount = Arrays.stream(updateCounts).sum(); + System.out.printf("Inserted %d singers\n", totalUpdateCount); + } + } +} +// [END spanner_postgresql_batch_dml] \ No newline at end of file diff --git a/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java b/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java new file mode 100644 index 00000000000..d76b26b1780 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java @@ -0,0 +1,154 @@ +/* + * 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.example.spanner; + +// [START spanner_postgresql_identifier_case_sensitivity] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ResultSet; +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.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.Collections; +import java.util.concurrent.ExecutionException; + +public class PgCaseSensitivitySample { + + static void pgCaseSensitivity() { + // TODO(developer): Replace these variables before running the sample. + final String projectId = "my-project"; + final String instanceId = "my-instance"; + final String databaseId = "my-database"; + pgCaseSensitivity(projectId, instanceId, databaseId); + } + + static void pgCaseSensitivity(String projectId, String instanceId, String databaseId) { + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + + // Spanner PostgreSQL follows the case sensitivity rules of PostgreSQL. This means that: + // 1. Identifiers that are not double-quoted are folded to lower case. + // 2. Identifiers that are double-quoted retain their case and are case-sensitive. + // See https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS + // for more information. + final OperationFuture updateOperation = + databaseAdminClient.updateDatabaseDdl( + instanceId, + databaseId, + Collections.singleton( + "CREATE TABLE Singers (" + // SingerId will be folded to `singerid`. + + " SingerId bigint NOT NULL PRIMARY KEY," + // FirstName and LastName are double-quoted and will therefore retain their + // mixed case and are case-sensitive. This means that any statement that + // references any of these columns must use double quotes. + + " \"FirstName\" varchar(1024) NOT NULL," + + " \"LastName\" varchar(1024) NOT NULL" + + ")"), + null); + updateOperation.get(); + + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); + + client.write( + Collections.singleton( + Mutation.newInsertBuilder("Singers") + .set("singerid") + .to(1L) + // Column names in mutations are always case-insensitive, regardless whether the + // columns were double-quoted or not during creation. + .set("firstname") + .to("Bruce") + .set("lastname") + .to("Allison") + .build())); + + try (ResultSet singers = + client + .singleUse() + .executeQuery( + Statement.of("SELECT SingerId, \"FirstName\", \"LastName\" FROM Singers"))) { + while (singers.next()) { + System.out.printf( + "SingerId: %d, FirstName: %s, LastName: %s\n", + // SingerId is automatically folded to lower case. Accessing the column by its name in + // a result set must therefore use all lower-case letters. + singers.getLong("singerid"), + // FirstName and LastName were double-quoted during creation, and retain their mixed + // case when returned in a result set. + singers.getString("FirstName"), + singers.getString("LastName")); + } + } + + // Aliases are also identifiers, and specifying an alias in double quotes will make the alias + // retain its case. + try (ResultSet singers = + client + .singleUse() + .executeQuery( + Statement.of( + "SELECT " + + "singerid AS \"SingerId\", " + + "concat(\"FirstName\", ' '::varchar, \"LastName\") AS \"FullName\" " + + "FROM Singers"))) { + while (singers.next()) { + System.out.printf( + "SingerId: %d, FullName: %s\n", + // The aliases are double-quoted and therefore retains their mixed case. + singers.getLong("SingerId"), singers.getString("FullName")); + } + } + + // DML statements must also follow the PostgreSQL case rules. + client + .readWriteTransaction() + .run( + transaction -> + transaction.executeUpdate( + Statement.newBuilder( + "INSERT INTO Singers (SingerId, \"FirstName\", \"LastName\") " + + "VALUES ($1, $2, $3)") + .bind("p1") + .to(2L) + .bind("p2") + .to("Alice") + .bind("p3") + .to("Bruxelles") + .build())); + } catch (ExecutionException e) { + // If the operation failed during execution, expose the cause. + throw SpannerExceptionFactory.asSpannerException(e.getCause()); + } catch (InterruptedException e) { + // Throw when a thread is waiting, sleeping, or otherwise occupied, + // and the thread is interrupted, either before or during the activity. + throw SpannerExceptionFactory.propagateInterrupt(e); + } + } +} +// [END spanner_postgresql_identifier_case_sensitivity] \ No newline at end of file diff --git a/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java b/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java new file mode 100644 index 00000000000..d79ba7b58fa --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java @@ -0,0 +1,81 @@ +/* + * 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.example.spanner; + +// [START spanner_postgresql_interleaved_table] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.Arrays; +import java.util.concurrent.ExecutionException; + +public class PgInterleavedTableSample { + + static void pgInterleavedTable() { + // TODO(developer): Replace these variables before running the sample. + final String projectId = "my-project"; + final String instanceId = "my-instance"; + final String databaseId = "my-database"; + pgInterleavedTable(projectId, instanceId, databaseId); + } + + static void pgInterleavedTable(String projectId, String instanceId, String databaseId) { + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + + // The Spanner PostgreSQL dialect extends the PostgreSQL dialect with certain Spanner + // specific features, such as interleaved tables. + // See https://cloud.google.com/spanner/docs/postgresql/data-definition-language#create_table + // for the full CREATE TABLE syntax. + final OperationFuture updateOperation = + databaseAdminClient.updateDatabaseDdl( + instanceId, + databaseId, + Arrays.asList( + "CREATE TABLE Singers (" + + " SingerId bigint NOT NULL PRIMARY KEY," + + " FirstName varchar(1024) NOT NULL," + + " LastName varchar(1024) NOT NULL" + + ")", + "CREATE TABLE Albums (" + + " SingerId bigint NOT NULL," + + " AlbumId bigint NOT NULL," + + " Title varchar(1024) NOT NULL," + + " PRIMARY KEY (SingerId, AlbumId)" + + ") INTERLEAVE IN PARENT Singers ON DELETE CASCADE"), + null); + updateOperation.get(); + System.out.println("Created interleaved table hierarchy using PostgreSQL dialect"); + } catch (ExecutionException e) { + // If the operation failed during execution, expose the cause. + throw SpannerExceptionFactory.asSpannerException(e.getCause()); + } catch (InterruptedException e) { + // Throw when a thread is waiting, sleeping, or otherwise occupied, + // and the thread is interrupted, either before or during the activity. + throw SpannerExceptionFactory.propagateInterrupt(e); + } + } +} +// [END spanner_postgresql_interleaved_table] \ No newline at end of file diff --git a/samples/snippets/src/main/java/com/example/spanner/PgPartitionedDmlSample.java b/samples/snippets/src/main/java/com/example/spanner/PgPartitionedDmlSample.java new file mode 100644 index 00000000000..ff442e7b2ef --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/PgPartitionedDmlSample.java @@ -0,0 +1,58 @@ +/* + * Copyright 2022 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. + */ + +package com.example.spanner; + +// [START spanner_postgresql_partitioned_dml] + +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.Statement; + +class PgPartitionedDmlSample { + + static void partitionedDml() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + + partitionedDml(projectId, instanceId, databaseId); + } + + static void partitionedDml(String projectId, String instanceId, String databaseId) { + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); + + // Spanner PostgreSQL has the same transaction limits as normal Spanner. This includes a + // maximum of 20,000 mutations in a single read/write transaction. Large update operations can + // be executed using Partitioned DML. This is also supported on Spanner PostgreSQL. + // See https://cloud.google.com/spanner/docs/dml-partitioned for more information. + long deletedCount = + client.executePartitionedUpdate(Statement.of("DELETE FROM users WHERE active=false")); + // The returned update count is the lower bound of the number of records that was deleted. + System.out.printf("Deleted at least %d inactive users\n", deletedCount); + } + } +} +// [END spanner_postgresql_partitioned_dml] \ No newline at end of file diff --git a/samples/snippets/src/test/java/com/example/spanner/PgBatchDmlSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/PgBatchDmlSampleIT.java new file mode 100644 index 00000000000..0b105d41b7d --- /dev/null +++ b/samples/snippets/src/test/java/com/example/spanner/PgBatchDmlSampleIT.java @@ -0,0 +1,59 @@ +/* + * 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.example.spanner; + +import static org.junit.Assert.assertTrue; + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.Collections; +import org.junit.Test; + +public class PgBatchDmlSampleIT extends SampleTestBase { + + @Test + public void testPgBatchDml() throws Exception { + final String databaseId = idGenerator.generateDatabaseId(); + databaseAdminClient + .createDatabase( + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.POSTGRESQL) + .build(), + Collections.emptyList()) + .get(); + final OperationFuture updateOperation = + databaseAdminClient.updateDatabaseDdl( + instanceId, + databaseId, + Collections.singleton( + "CREATE TABLE Singers (" + + " SingerId bigint NOT NULL PRIMARY KEY," + + " FirstName varchar(1024)," + + " LastName varchar(1024)" + + ")"), + null); + updateOperation.get(); + + final String out = + SampleRunner.runSample(() -> PgBatchDmlSample.batchDml(projectId, instanceId, databaseId)); + + assertTrue(out.contains("Inserted 2 singers")); + } +} \ No newline at end of file diff --git a/samples/snippets/src/test/java/com/example/spanner/PgCaseSensitivitySampleIT.java b/samples/snippets/src/test/java/com/example/spanner/PgCaseSensitivitySampleIT.java new file mode 100644 index 00000000000..1c2bca587ce --- /dev/null +++ b/samples/snippets/src/test/java/com/example/spanner/PgCaseSensitivitySampleIT.java @@ -0,0 +1,46 @@ +/* + * 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.example.spanner; + +import static org.junit.Assert.assertTrue; + +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import java.util.Collections; +import org.junit.Test; + +public class PgCaseSensitivitySampleIT extends SampleTestBase { + + @Test + public void testPgCaseSensitivitySample() throws Exception { + final String databaseId = idGenerator.generateDatabaseId(); + databaseAdminClient + .createDatabase( + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.POSTGRESQL) + .build(), + Collections.emptyList()) + .get(); + + final String out = + SampleRunner.runSample( + () -> PgCaseSensitivitySample.pgCaseSensitivity(projectId, instanceId, databaseId)); + assertTrue(out, out.contains("SingerId: 1, FirstName: Bruce, LastName: Allison")); + assertTrue(out, out.contains("SingerId: 1, FullName: Bruce Allison")); + } +} \ No newline at end of file diff --git a/samples/snippets/src/test/java/com/example/spanner/PgInterleavedTableSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/PgInterleavedTableSampleIT.java new file mode 100644 index 00000000000..6678f2a471d --- /dev/null +++ b/samples/snippets/src/test/java/com/example/spanner/PgInterleavedTableSampleIT.java @@ -0,0 +1,45 @@ +/* + * 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.example.spanner; + +import static org.junit.Assert.assertTrue; + +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import java.util.Collections; +import org.junit.Test; + +public class PgInterleavedTableSampleIT extends SampleTestBase { + + @Test + public void testPgInterleavedTableSample() throws Exception { + final String databaseId = idGenerator.generateDatabaseId(); + databaseAdminClient + .createDatabase( + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.POSTGRESQL) + .build(), + Collections.emptyList()) + .get(); + + final String out = + SampleRunner.runSample( + () -> PgInterleavedTableSample.pgInterleavedTable(projectId, instanceId, databaseId)); + assertTrue(out.contains("Created interleaved table hierarchy using PostgreSQL dialect")); + } +} \ No newline at end of file diff --git a/samples/snippets/src/test/java/com/example/spanner/PgPartitionedDmlSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/PgPartitionedDmlSampleIT.java new file mode 100644 index 00000000000..26d7a37b643 --- /dev/null +++ b/samples/snippets/src/test/java/com/example/spanner/PgPartitionedDmlSampleIT.java @@ -0,0 +1,91 @@ +/* + * 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.example.spanner; + +import static org.junit.Assert.assertTrue; + +import com.google.api.gax.longrunning.OperationFuture; +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.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.Arrays; +import java.util.Collections; +import org.junit.Test; + +public class PgPartitionedDmlSampleIT extends SampleTestBase { + + @Test + public void testPgPartitionedDml() throws Exception { + final String databaseId = idGenerator.generateDatabaseId(); + databaseAdminClient + .createDatabase( + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.POSTGRESQL) + .build(), + Collections.emptyList()) + .get(); + final OperationFuture updateOperation = + databaseAdminClient.updateDatabaseDdl( + instanceId, + databaseId, + Collections.singleton( + "CREATE TABLE users (" + + " user_id bigint NOT NULL PRIMARY KEY," + + " user_name varchar(1024)," + + " active boolean" + + ")"), + null); + updateOperation.get(); + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); + client.write( + Arrays.asList( + Mutation.newInsertBuilder("users") + .set("user_id") + .to(1L) + .set("user_name") + .to("user1") + .set("active") + .to(false) + .build(), + Mutation.newInsertBuilder("users") + .set("user_id") + .to(2L) + .set("user_name") + .to("user2") + .set("active") + .to(false) + .build(), + Mutation.newInsertBuilder("users") + .set("user_id") + .to(3L) + .set("user_name") + .to("user3") + .set("active") + .to(true) + .build())); + + final String out = + SampleRunner.runSample( + () -> PgPartitionedDmlSample.partitionedDml(projectId, instanceId, databaseId)); + + assertTrue(out.contains("Deleted at least 2 inactive users")); + } +} \ No newline at end of file diff --git a/versions.txt b/versions.txt index fdaab8e6dfb..6bf8c6f7c30 100644 --- a/versions.txt +++ b/versions.txt @@ -1,10 +1,10 @@ # Format: # module:released-version:current-version -proto-google-cloud-spanner-admin-instance-v1:6.23.2:6.23.2 -proto-google-cloud-spanner-v1:6.23.2:6.23.2 -proto-google-cloud-spanner-admin-database-v1:6.23.2:6.23.2 -grpc-google-cloud-spanner-v1:6.23.2:6.23.2 -grpc-google-cloud-spanner-admin-instance-v1:6.23.2:6.23.2 -grpc-google-cloud-spanner-admin-database-v1:6.23.2:6.23.2 -google-cloud-spanner:6.23.2:6.23.2 +proto-google-cloud-spanner-admin-instance-v1:6.23.3:6.23.3 +proto-google-cloud-spanner-v1:6.23.3:6.23.3 +proto-google-cloud-spanner-admin-database-v1:6.23.3:6.23.3 +grpc-google-cloud-spanner-v1:6.23.3:6.23.3 +grpc-google-cloud-spanner-admin-instance-v1:6.23.3:6.23.3 +grpc-google-cloud-spanner-admin-database-v1:6.23.3:6.23.3 +google-cloud-spanner:6.23.3:6.23.3