Skip to content

Commit

Permalink
docs: samples and tests for database Admin APIs. (#2775)
Browse files Browse the repository at this point in the history
Adds samples and tests for auto-generated Database Admin APIs.
  • Loading branch information
arpan14 authored Feb 15, 2024
1 parent c8632f5 commit 14ae01c
Show file tree
Hide file tree
Showing 40 changed files with 2,515 additions and 182 deletions.
23 changes: 22 additions & 1 deletion README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<groupId>com.google.cloud.samples</groupId>
<artifactId>shared-configuration</artifactId>
<version>1.2.0</version>
<relativePath></relativePath>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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.admin.generated;

// [START spanner_add_and_drop_database_role]

import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient;
import com.google.common.collect.ImmutableList;
import com.google.spanner.admin.database.v1.DatabaseName;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AddAndDropDatabaseRole {

static void addAndDropDatabaseRole() throws IOException {
// TODO(developer): Replace these variables before running the sample.
String projectId = "my-project";
String instanceId = "my-instance";
String databaseId = "my-database";
String parentRole = "parent_role";
String childRole = "child_role";
addAndDropDatabaseRole(projectId, instanceId, databaseId, parentRole, childRole);
}

static void addAndDropDatabaseRole(
String projectId, String instanceId, String databaseId, String parentRole, String childRole)
throws IOException {
final DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create();
try {
System.out.println("Waiting for role create operation to complete...");
databaseAdminClient.updateDatabaseDdlAsync(
DatabaseName.of(projectId, instanceId, databaseId),
ImmutableList.of(
String.format("CREATE ROLE %s", parentRole),
String.format("GRANT SELECT ON TABLE Albums TO ROLE %s", parentRole),
String.format("CREATE ROLE %s", childRole),
String.format("GRANT ROLE %s TO ROLE %s", parentRole, childRole)))
.get(5, TimeUnit.MINUTES);
System.out.printf(
"Created roles %s and %s and granted privileges%n", parentRole, childRole);
// Delete role and membership.
System.out.println("Waiting for role revoke & drop operation to complete...");
databaseAdminClient.updateDatabaseDdlAsync(
DatabaseName.of(projectId, instanceId, databaseId),
ImmutableList.of(
String.format("REVOKE ROLE %s FROM ROLE %s", parentRole, childRole),
String.format("DROP ROLE %s", childRole))).get(5, TimeUnit.MINUTES);
System.out.printf("Revoked privileges and dropped role %s%n", childRole);
} catch (ExecutionException | TimeoutException e) {
System.out.printf(
"Error: AddAndDropDatabaseRole failed with error message %s\n", e.getMessage());
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println(
"Error: Waiting for AddAndDropDatabaseRole operation to finish was interrupted");
}
}
}
// [END spanner_add_and_drop_database_role]
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.
*/

package com.example.spanner.admin.generated;

// [START spanner_add_json_column]
import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient;
import com.google.common.collect.ImmutableList;
import com.google.spanner.admin.database.v1.DatabaseName;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

class AddJsonColumnSample {

static void addJsonColumn() throws InterruptedException, ExecutionException, IOException {
// TODO(developer): Replace these variables before running the sample.
String projectId = "my-project";
String instanceId = "my-instance";
String databaseId = "my-database";

addJsonColumn(projectId, instanceId, databaseId);
}

static void addJsonColumn(String projectId, String instanceId, String databaseId)
throws InterruptedException, ExecutionException, IOException {
final DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create();

// Wait for the operation to finish.
// This will throw an ExecutionException if the operation fails.
databaseAdminClient.updateDatabaseDdlAsync(
DatabaseName.of(projectId, instanceId, databaseId),
ImmutableList.of("ALTER TABLE Venues ADD COLUMN VenueDetails JSON")).get();
System.out.printf("Successfully added column `VenueDetails`%n");
}
}
// [END spanner_add_json_column]
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.admin.generated;

// [START spanner_postgresql_jsonb_add_column]
import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient;
import com.google.common.collect.ImmutableList;
import com.google.spanner.admin.database.v1.DatabaseName;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

class AddJsonbColumnSample {

static void addJsonbColumn() throws InterruptedException, ExecutionException, IOException {
// TODO(developer): Replace these variables before running the sample.
String projectId = "my-project";
String instanceId = "my-instance";
String databaseId = "my-database";

addJsonbColumn(projectId, instanceId, databaseId);
}

static void addJsonbColumn(String projectId, String instanceId, String databaseId)
throws InterruptedException, ExecutionException, IOException {
final DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create();

// JSONB datatype is only supported with PostgreSQL-dialect databases.
// Wait for the operation to finish.
// This will throw an ExecutionException if the operation fails.
databaseAdminClient.updateDatabaseDdlAsync(
DatabaseName.of(projectId, instanceId, databaseId),
ImmutableList.of("ALTER TABLE Venues ADD COLUMN VenueDetails JSONB")).get();
System.out.printf("Successfully added column `VenueDetails`%n");
}
}
// [END spanner_postgresql_jsonb_add_column]
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2020 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.admin.generated;

// [START spanner_add_numeric_column]

import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient;
import com.google.common.collect.ImmutableList;
import com.google.spanner.admin.database.v1.DatabaseName;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

class AddNumericColumnSample {

static void addNumericColumn() throws InterruptedException, ExecutionException, IOException {
// TODO(developer): Replace these variables before running the sample.
String projectId = "my-project";
String instanceId = "my-instance";
String databaseId = "my-database";

addNumericColumn(projectId, instanceId, databaseId);
}

static void addNumericColumn(String projectId, String instanceId, String databaseId)
throws InterruptedException, ExecutionException, IOException {
final DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create();

// Wait for the operation to finish.
// This will throw an ExecutionException if the operation fails.
databaseAdminClient.updateDatabaseDdlAsync(
DatabaseName.of(projectId, instanceId, databaseId),
ImmutableList.of("ALTER TABLE Venues ADD COLUMN Revenue NUMERIC")).get();
System.out.printf("Successfully added column `Revenue`%n");
}
}
// [END spanner_add_numeric_column]
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* 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.example.spanner.admin.generated;

// [START spanner_alter_sequence]

import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
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.cloud.spanner.admin.database.v1.DatabaseAdminClient;
import com.google.common.collect.ImmutableList;
import com.google.spanner.admin.database.v1.DatabaseName;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AlterSequenceSample {

static void alterSequence() throws IOException {
// TODO(developer): Replace these variables before running the sample.
final String projectId = "my-project";
final String instanceId = "my-instance";
final String databaseId = "my-database";
alterSequence(projectId, instanceId, databaseId);
}

static void alterSequence(String projectId, String instanceId, String databaseId)
throws IOException {
DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create();
try (Spanner spanner =
SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {

databaseAdminClient
.updateDatabaseDdlAsync(DatabaseName.of(projectId, instanceId, databaseId),
ImmutableList.of(
"ALTER SEQUENCE Seq SET OPTIONS "
+ "(skip_range_min = 1000, skip_range_max = 5000000)"))
.get(5, TimeUnit.MINUTES);

System.out.println(
"Altered Seq sequence to skip an inclusive range between 1000 and 5000000");

final DatabaseClient dbClient =
spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));

Long insertCount =
dbClient
.readWriteTransaction()
.run(
transaction -> {
try (ResultSet rs =
transaction.executeQuery(
Statement.of(
"INSERT INTO Customers (CustomerName) VALUES "
+ "('Lea'), ('Catalina'), ('Smith') "
+ "THEN RETURN CustomerId"))) {
while (rs.next()) {
System.out.printf(
"Inserted customer record with CustomerId: %d\n", rs.getLong(0));
}
return Objects.requireNonNull(rs.getStats()).getRowCountExact();
}
});
System.out.printf("Number of customer records inserted is: %d\n", insertCount);
} 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);
} catch (TimeoutException e) {
// If the operation timed out propagate the timeout
throw SpannerExceptionFactory.propagateTimeout(e);
}
}
}
// [END spanner_alter_sequence]
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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.example.spanner.admin.generated;

// [START spanner_alter_table_with_foreign_key_delete_cascade]

import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient;
import com.google.common.collect.ImmutableList;
import com.google.spanner.admin.database.v1.DatabaseName;
import java.io.IOException;

class AlterTableWithForeignKeyDeleteCascadeSample {

static void alterForeignKeyDeleteCascadeConstraint() throws IOException {
// TODO(developer): Replace these variables before running the sample.
String projectId = "my-project";
String instanceId = "my-instance";
String databaseId = "my-database";

alterForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId);
}

static void alterForeignKeyDeleteCascadeConstraint(
String projectId, String instanceId, String databaseId) throws IOException {
DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create();

databaseAdminClient.updateDatabaseDdlAsync(DatabaseName.of(projectId, instanceId,
databaseId),
ImmutableList.of(
"ALTER TABLE ShoppingCarts\n"
+ " ADD CONSTRAINT FKShoppingCartsCustomerName\n"
+ " FOREIGN KEY (CustomerName)\n"
+ " REFERENCES Customers(CustomerName)\n"
+ " ON DELETE CASCADE\n"));
System.out.printf(
String.format(
"Altered ShoppingCarts table with FKShoppingCartsCustomerName\n"
+ "foreign key constraint on database %s on instance %s",
databaseId, instanceId));
}
}
// [END spanner_alter_table_with_foreign_key_delete_cascade]
Loading

0 comments on commit 14ae01c

Please sign in to comment.