diff --git a/README.md b/README.md index 2ed6ff04b4..2172a1582f 100644 --- a/README.md +++ b/README.md @@ -509,43 +509,44 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/ | Update Jsonb Data Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UpdateJsonbDataSample.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/UpdateJsonbDataSample.java) | | Update Numeric Data Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UpdateNumericDataSample.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/UpdateNumericDataSample.java) | | Update Using Dml Returning Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UpdateUsingDmlReturningSample.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/UpdateUsingDmlReturningSample.java) | -| Add And Drop Database Role | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddAndDropDatabaseRole.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/admin/generated/AddAndDropDatabaseRole.java) | -| Add Json Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddJsonColumnSample.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/admin/generated/AddJsonColumnSample.java) | -| Add Jsonb Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddJsonbColumnSample.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/admin/generated/AddJsonbColumnSample.java) | -| Add Numeric Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddNumericColumnSample.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/admin/generated/AddNumericColumnSample.java) | -| Alter Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/AlterSequenceSample.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/admin/generated/AlterSequenceSample.java) | -| Alter Table With Foreign Key Delete Cascade Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/AlterTableWithForeignKeyDeleteCascadeSample.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/admin/generated/AlterTableWithForeignKeyDeleteCascadeSample.java) | -| Copy Backup Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CopyBackupSample.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/admin/generated/CopyBackupSample.java) | -| Create Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateBackupWithEncryptionKey.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/admin/generated/CreateBackupWithEncryptionKey.java) | -| Create Database With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateDatabaseWithEncryptionKey.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/admin/generated/CreateDatabaseWithEncryptionKey.java) | -| Create Database With Version Retention Period Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateDatabaseWithVersionRetentionPeriodSample.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/admin/generated/CreateDatabaseWithVersionRetentionPeriodSample.java) | -| Create Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceConfigSample.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/admin/generated/CreateInstanceConfigSample.java) | -| Create Instance Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceExample.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/admin/generated/CreateInstanceExample.java) | -| Create Instance With Autoscaling Config Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceWithAutoscalingConfigExample.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/admin/generated/CreateInstanceWithAutoscalingConfigExample.java) | -| Create Instance With Processing Units Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceWithProcessingUnitsExample.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/admin/generated/CreateInstanceWithProcessingUnitsExample.java) | -| Create Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateSequenceSample.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/admin/generated/CreateSequenceSample.java) | -| Create Table With Foreign Key Delete Cascade Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateTableWithForeignKeyDeleteCascadeSample.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/admin/generated/CreateTableWithForeignKeyDeleteCascadeSample.java) | -| Delete Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/DeleteInstanceConfigSample.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/admin/generated/DeleteInstanceConfigSample.java) | -| Drop Foreign Key Constraint Delete Cascade Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/DropForeignKeyConstraintDeleteCascadeSample.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/admin/generated/DropForeignKeyConstraintDeleteCascadeSample.java) | -| Drop Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/DropSequenceSample.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/admin/generated/DropSequenceSample.java) | -| Enable Fine Grained Access | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/EnableFineGrainedAccess.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/admin/generated/EnableFineGrainedAccess.java) | -| Get Database Ddl Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/GetDatabaseDdlSample.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/admin/generated/GetDatabaseDdlSample.java) | -| Get Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/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/admin/generated/GetInstanceConfigSample.java) | -| List Database Roles | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListDatabaseRoles.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/admin/generated/ListDatabaseRoles.java) | -| List Databases Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/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/admin/generated/ListDatabasesSample.java) | -| List Instance Config Operations Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListInstanceConfigOperationsSample.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/admin/generated/ListInstanceConfigOperationsSample.java) | -| List Instance Configs Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/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/admin/generated/ListInstanceConfigsSample.java) | -| Pg Alter Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgAlterSequenceSample.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/admin/generated/PgAlterSequenceSample.java) | -| Pg Case Sensitivity Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/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/admin/generated/PgCaseSensitivitySample.java) | -| Pg Create Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgCreateSequenceSample.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/admin/generated/PgCreateSequenceSample.java) | -| Pg Drop Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgDropSequenceSample.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/admin/generated/PgDropSequenceSample.java) | -| Pg Interleaved Table Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/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/admin/generated/PgInterleavedTableSample.java) | -| Pg Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgSpannerSample.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/admin/generated/PgSpannerSample.java) | -| Restore Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/RestoreBackupWithEncryptionKey.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/admin/generated/RestoreBackupWithEncryptionKey.java) | -| Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/SpannerSample.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/admin/generated/SpannerSample.java) | -| Update Database Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateDatabaseSample.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/admin/generated/UpdateDatabaseSample.java) | -| Update Database With Default Leader Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateDatabaseWithDefaultLeaderSample.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/admin/generated/UpdateDatabaseWithDefaultLeaderSample.java) | -| Update Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateInstanceConfigSample.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/admin/generated/UpdateInstanceConfigSample.java) | +| Add And Drop Database Role | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddAndDropDatabaseRole.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/admin/archived/AddAndDropDatabaseRole.java) | +| Add Json Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddJsonColumnSample.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/admin/archived/AddJsonColumnSample.java) | +| Add Jsonb Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddJsonbColumnSample.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/admin/archived/AddJsonbColumnSample.java) | +| Add Numeric Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddNumericColumnSample.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/admin/archived/AddNumericColumnSample.java) | +| Alter Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/AlterSequenceSample.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/admin/archived/AlterSequenceSample.java) | +| Alter Table With Foreign Key Delete Cascade Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/AlterTableWithForeignKeyDeleteCascadeSample.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/admin/archived/AlterTableWithForeignKeyDeleteCascadeSample.java) | +| Copy Backup Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CopyBackupSample.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/admin/archived/CopyBackupSample.java) | +| Create Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateBackupWithEncryptionKey.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/admin/archived/CreateBackupWithEncryptionKey.java) | +| Create Database With Default Leader Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithDefaultLeaderSample.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/admin/archived/CreateDatabaseWithDefaultLeaderSample.java) | +| Create Database With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithEncryptionKey.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/admin/archived/CreateDatabaseWithEncryptionKey.java) | +| Create Database With Version Retention Period Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithVersionRetentionPeriodSample.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/admin/archived/CreateDatabaseWithVersionRetentionPeriodSample.java) | +| Create Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceConfigSample.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/admin/archived/CreateInstanceConfigSample.java) | +| Create Instance Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceExample.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/admin/archived/CreateInstanceExample.java) | +| Create Instance With Autoscaling Config Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigExample.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/admin/archived/CreateInstanceWithAutoscalingConfigExample.java) | +| Create Instance With Processing Units Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithProcessingUnitsExample.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/admin/archived/CreateInstanceWithProcessingUnitsExample.java) | +| Create Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateSequenceSample.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/admin/archived/CreateSequenceSample.java) | +| Create Table With Foreign Key Delete Cascade Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateTableWithForeignKeyDeleteCascadeSample.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/admin/archived/CreateTableWithForeignKeyDeleteCascadeSample.java) | +| Delete Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/DeleteInstanceConfigSample.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/admin/archived/DeleteInstanceConfigSample.java) | +| Drop Foreign Key Constraint Delete Cascade Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/DropForeignKeyConstraintDeleteCascadeSample.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/admin/archived/DropForeignKeyConstraintDeleteCascadeSample.java) | +| Drop Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/DropSequenceSample.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/admin/archived/DropSequenceSample.java) | +| Enable Fine Grained Access | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/EnableFineGrainedAccess.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/admin/archived/EnableFineGrainedAccess.java) | +| Get Database Ddl Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/GetDatabaseDdlSample.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/admin/archived/GetDatabaseDdlSample.java) | +| Get Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/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/admin/archived/GetInstanceConfigSample.java) | +| List Database Roles | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListDatabaseRoles.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/admin/archived/ListDatabaseRoles.java) | +| List Databases Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/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/admin/archived/ListDatabasesSample.java) | +| List Instance Config Operations Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListInstanceConfigOperationsSample.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/admin/archived/ListInstanceConfigOperationsSample.java) | +| List Instance Configs Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/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/admin/archived/ListInstanceConfigsSample.java) | +| Pg Alter Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgAlterSequenceSample.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/admin/archived/PgAlterSequenceSample.java) | +| Pg Case Sensitivity Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/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/admin/archived/PgCaseSensitivitySample.java) | +| Pg Create Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgCreateSequenceSample.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/admin/archived/PgCreateSequenceSample.java) | +| Pg Drop Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgDropSequenceSample.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/admin/archived/PgDropSequenceSample.java) | +| Pg Interleaved Table Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/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/admin/archived/PgInterleavedTableSample.java) | +| Pg Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgSpannerSample.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/admin/archived/PgSpannerSample.java) | +| Restore Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/RestoreBackupWithEncryptionKey.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/admin/archived/RestoreBackupWithEncryptionKey.java) | +| Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/SpannerSample.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/admin/archived/SpannerSample.java) | +| Update Database Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateDatabaseSample.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/admin/archived/UpdateDatabaseSample.java) | +| Update Database With Default Leader Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateDatabaseWithDefaultLeaderSample.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/admin/archived/UpdateDatabaseWithDefaultLeaderSample.java) | +| Update Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateInstanceConfigSample.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/admin/archived/UpdateInstanceConfigSample.java) | diff --git a/samples/README.md b/samples/README.md index 9f961354d9..914c455b46 100644 --- a/samples/README.md +++ b/samples/README.md @@ -34,7 +34,7 @@ You can run a given `ClassName` via: ## Tutorial ### Running the tutorial - mvn exec:java -Dexec.mainClass=com.example.spanner.SpannerSample -Dexec.args=" my-instance my-database" + mvn exec:java -Dexec.mainClass=com.example.spanner.admin.archived.SpannerSample -Dexec.args=" my-instance my-database" ## Tracing sample `TracingSample.java` demonstrates how to export traces generated by client library to StackDriver and to /tracez page. diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index e8d2155b33..4103b4ad8e 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -165,7 +165,7 @@ false - com.example.spanner.SpannerSample + com.example.spanner.admin.archived.SpannerSample true lib/ diff --git a/samples/snippets/src/main/java/com/example/spanner/AddAndDropDatabaseRole.java b/samples/snippets/src/main/java/com/example/spanner/AddAndDropDatabaseRole.java index 2d65974099..75e85f5f85 100644 --- a/samples/snippets/src/main/java/com/example/spanner/AddAndDropDatabaseRole.java +++ b/samples/snippets/src/main/java/com/example/spanner/AddAndDropDatabaseRole.java @@ -17,12 +17,12 @@ package com.example.spanner; // [START spanner_add_and_drop_database_role] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -34,54 +34,46 @@ static void addAndDropDatabaseRole() { String projectId = "my-project"; String instanceId = "my-instance"; String databaseId = "my-database"; - String parentRole = "my-new-parent-role"; - String childRole = "my-new-child-role"; + 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) { + String projectId, String instanceId, String databaseId, + String parentRole, String childRole) { try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - OperationFuture operation = - adminClient.updateDatabaseDdl( - instanceId, - databaseId, + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + System.out.println("Waiting for role create operation to complete..."); + databaseAdminClient.updateDatabaseDdlAsync( + DatabaseName.of(projectId, instanceId, databaseId), ImmutableList.of( - "CREATE ROLE " + parentRole, - "GRANT SELECT ON TABLE Albums TO ROLE " + parentRole, - "CREATE ROLE " + childRole, - "GRANT ROLE " + parentRole + " TO ROLE " + childRole), - null); - try { - System.out.println("Waiting for role create operation to complete..."); - operation.get(5, TimeUnit.MINUTES); - System.out.printf( - "Created roles %s and %s and granted privileges%n", parentRole, childRole); - // Delete role and membership. - operation = - adminClient.updateDatabaseDdl( - instanceId, - databaseId, - ImmutableList.of( - "REVOKE ROLE " + parentRole + " FROM ROLE " + childRole, - "DROP ROLE " + childRole), - null); - System.out.println("Waiting for role revoke & drop operation to complete..."); - operation.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"); - } + 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"); } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/AddJsonColumnSample.java b/samples/snippets/src/main/java/com/example/spanner/AddJsonColumnSample.java index 8be919ddad..c87b25ff47 100644 --- a/samples/snippets/src/main/java/com/example/spanner/AddJsonColumnSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/AddJsonColumnSample.java @@ -17,12 +17,12 @@ package com.example.spanner; // [START spanner_add_json_column] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.concurrent.ExecutionException; class AddJsonColumnSample { @@ -33,25 +33,24 @@ static void addJsonColumn() throws InterruptedException, ExecutionException { String instanceId = "my-instance"; String databaseId = "my-database"; - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - addJsonColumn(adminClient, instanceId, databaseId); - } + addJsonColumn(projectId, instanceId, databaseId); } - static void addJsonColumn(DatabaseAdminClient adminClient, String instanceId, String databaseId) + static void addJsonColumn(String projectId, String instanceId, String databaseId) throws InterruptedException, ExecutionException { - OperationFuture operation = - adminClient.updateDatabaseDdl( - instanceId, - databaseId, - ImmutableList.of("ALTER TABLE Venues ADD COLUMN VenueDetails JSON"), - null); - // Wait for the operation to finish. - // This will throw an ExecutionException if the operation fails. - operation.get(); - System.out.printf("Successfully added column `VenueDetails`%n"); + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + // 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] diff --git a/samples/snippets/src/main/java/com/example/spanner/AddJsonbColumnSample.java b/samples/snippets/src/main/java/com/example/spanner/AddJsonbColumnSample.java index e8152c4fa0..ab2607c498 100644 --- a/samples/snippets/src/main/java/com/example/spanner/AddJsonbColumnSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/AddJsonbColumnSample.java @@ -17,12 +17,12 @@ package com.example.spanner; // [START spanner_postgresql_jsonb_add_column] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.concurrent.ExecutionException; class AddJsonbColumnSample { @@ -33,25 +33,25 @@ static void addJsonbColumn() throws InterruptedException, ExecutionException { String instanceId = "my-instance"; String databaseId = "my-database"; - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - addJsonbColumn(adminClient, instanceId, databaseId); - } + addJsonbColumn(projectId, instanceId, databaseId); } - static void addJsonbColumn(DatabaseAdminClient adminClient, String instanceId, String databaseId) + static void addJsonbColumn(String projectId, String instanceId, String databaseId) throws InterruptedException, ExecutionException { - OperationFuture operation = - adminClient.updateDatabaseDdl( - instanceId, - databaseId, - ImmutableList.of("ALTER TABLE Venues ADD COLUMN VenueDetails JSONB"), - null); - // Wait for the operation to finish. - // This will throw an ExecutionException if the operation fails. - operation.get(); - System.out.printf("Successfully added column `VenueDetails`%n"); + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + // 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] diff --git a/samples/snippets/src/main/java/com/example/spanner/AddNumericColumnSample.java b/samples/snippets/src/main/java/com/example/spanner/AddNumericColumnSample.java index 7d29cdf15d..00cfb848e7 100644 --- a/samples/snippets/src/main/java/com/example/spanner/AddNumericColumnSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/AddNumericColumnSample.java @@ -17,12 +17,12 @@ package com.example.spanner; // [START spanner_add_numeric_column] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.concurrent.ExecutionException; class AddNumericColumnSample { @@ -33,26 +33,24 @@ static void addNumericColumn() throws InterruptedException, ExecutionException { String instanceId = "my-instance"; String databaseId = "my-database"; - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - addNumericColumn(adminClient, instanceId, databaseId); - } + addNumericColumn(projectId, instanceId, databaseId); } - static void addNumericColumn( - DatabaseAdminClient adminClient, String instanceId, String databaseId) + static void addNumericColumn(String projectId, String instanceId, String databaseId) throws InterruptedException, ExecutionException { - OperationFuture operation = - adminClient.updateDatabaseDdl( - instanceId, - databaseId, - ImmutableList.of("ALTER TABLE Venues ADD COLUMN Revenue NUMERIC"), - null); - // Wait for the operation to finish. - // This will throw an ExecutionException if the operation fails. - operation.get(); - System.out.printf("Successfully added column `Revenue`%n"); + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + // 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] diff --git a/samples/snippets/src/main/java/com/example/spanner/AlterSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/AlterSequenceSample.java index 6b9014a26f..641449ace9 100644 --- a/samples/snippets/src/main/java/com/example/spanner/AlterSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/AlterSequenceSample.java @@ -17,7 +17,7 @@ package com.example.spanner; // [START spanner_alter_sequence] -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ResultSet; @@ -25,13 +25,16 @@ 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.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class AlterSequenceSample { + static void alterSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -42,17 +45,14 @@ static void alterSequence() { static void alterSequence(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - dbAdminClient - .updateDatabaseDdl( - instanceId, - databaseId, + databaseAdminClient + .updateDatabaseDdlAsync(DatabaseName.of(projectId, instanceId, databaseId), ImmutableList.of( "ALTER SEQUENCE Seq SET OPTIONS " - + "(skip_range_min = 1000, skip_range_max = 5000000)"), - null) + + "(skip_range_min = 1000, skip_range_max = 5000000)")) .get(5, TimeUnit.MINUTES); System.out.println( diff --git a/samples/snippets/src/main/java/com/example/spanner/AlterTableWithForeignKeyDeleteCascadeSample.java b/samples/snippets/src/main/java/com/example/spanner/AlterTableWithForeignKeyDeleteCascadeSample.java index 1caf26fb28..6950e6a4fa 100644 --- a/samples/snippets/src/main/java/com/example/spanner/AlterTableWithForeignKeyDeleteCascadeSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/AlterTableWithForeignKeyDeleteCascadeSample.java @@ -17,10 +17,12 @@ package com.example.spanner; // [START spanner_alter_table_with_foreign_key_delete_cascade] -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.DatabaseName; class AlterTableWithForeignKeyDeleteCascadeSample { @@ -30,30 +32,28 @@ static void alterForeignKeyDeleteCascadeConstraint() { String instanceId = "my-instance"; String databaseId = "my-database"; - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - alterForeignKeyDeleteCascadeConstraint(adminClient, instanceId, databaseId); - } + alterForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId); } static void alterForeignKeyDeleteCascadeConstraint( - DatabaseAdminClient adminClient, String instanceId, String databaseId) { - adminClient.updateDatabaseDdl( - instanceId, - databaseId, - ImmutableList.of( - "ALTER TABLE ShoppingCarts\n" - + " ADD CONSTRAINT FKShoppingCartsCustomerName\n" - + " FOREIGN KEY (CustomerName)\n" - + " REFERENCES Customers(CustomerName)\n" - + " ON DELETE CASCADE\n"), - null); - System.out.printf( - String.format( - "Altered ShoppingCarts table with FKShoppingCartsCustomerName\n" - + "foreign key constraint on database %s on instance %s", - databaseId, instanceId)); + String projectId, String instanceId, String databaseId) { + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + 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] diff --git a/samples/snippets/src/main/java/com/example/spanner/CopyBackupSample.java b/samples/snippets/src/main/java/com/example/spanner/CopyBackupSample.java index 795edcb15a..c6ee706687 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CopyBackupSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CopyBackupSample.java @@ -18,84 +18,80 @@ // [START spanner_copy_backup] -import com.google.api.gax.longrunning.OperationFuture; import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Backup; -import com.google.cloud.spanner.BackupId; -import com.google.cloud.spanner.DatabaseAdminClient; 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.spanner.admin.database.v1.CopyBackupMetadata; -import java.time.LocalDateTime; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.spanner.admin.database.v1.Backup; +import com.google.spanner.admin.database.v1.BackupName; +import com.google.spanner.admin.database.v1.InstanceName; +import java.time.Instant; import java.time.OffsetDateTime; +import java.time.ZoneId; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; public class CopyBackupSample { + static void copyBackup() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; String instanceId = "my-instance"; String sourceBackupId = "my-backup"; String destinationBackupId = "my-destination-backup"; + try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { copyBackup(databaseAdminClient, projectId, instanceId, sourceBackupId, destinationBackupId); } } static void copyBackup( - DatabaseAdminClient databaseAdminClient, - String projectId, - String instanceId, - String sourceBackupId, - String destinationBackupId) { + DatabaseAdminClient databaseAdminClient, + String projectId, + String instanceId, + String sourceBackupId, + String destinationBackupId) { Timestamp expireTime = - Timestamp.ofTimeMicroseconds( - TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), - TimeUnit.MILLISECONDS)); - // Creates a copy of an existing backup. - Backup destinationBackup = - databaseAdminClient - .newBackupBuilder(BackupId.of(projectId, instanceId, destinationBackupId)) - .setExpireTime(expireTime) - .build(); + Timestamp.ofTimeMicroseconds( + TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), + TimeUnit.MILLISECONDS)); // Initiate the request which returns an OperationFuture. - System.out.println("Copying backup [" + destinationBackup.getId() + "]..."); - OperationFuture operation = - databaseAdminClient.copyBackup( - BackupId.of(projectId, instanceId, sourceBackupId), destinationBackup); + System.out.println("Copying backup [" + destinationBackupId + "]..."); + Backup destinationBackup; try { + // Creates a copy of an existing backup. // Wait for the backup operation to complete. - destinationBackup = operation.get(); - System.out.println("Copied backup [" + destinationBackup.getId() + "]"); + destinationBackup = databaseAdminClient.copyBackupAsync( + InstanceName.of(projectId, instanceId), destinationBackupId, + BackupName.of(projectId, instanceId, sourceBackupId), expireTime.toProto()).get(); + System.out.println("Copied backup [" + destinationBackup.getName() + "]"); } catch (ExecutionException e) { throw (SpannerException) e.getCause(); } catch (InterruptedException e) { throw SpannerExceptionFactory.propagateInterrupt(e); } // Load the metadata of the new backup from the server. - destinationBackup = destinationBackup.reload(); + destinationBackup = databaseAdminClient.getBackup(destinationBackup.getName()); System.out.println( - String.format( - "Backup %s of size %d bytes was copied at %s for version of database at %s", - destinationBackup.getId().getName(), - destinationBackup.getSize(), - LocalDateTime.ofEpochSecond( - destinationBackup.getProto().getCreateTime().getSeconds(), - destinationBackup.getProto().getCreateTime().getNanos(), - OffsetDateTime.now().getOffset()), - LocalDateTime.ofEpochSecond( - destinationBackup.getProto().getVersionTime().getSeconds(), - destinationBackup.getProto().getVersionTime().getNanos(), - OffsetDateTime.now().getOffset()))); - return; + String.format( + "Backup %s of size %d bytes was copied at %s for version of database at %s", + destinationBackup.getName(), + destinationBackup.getSizeBytes(), + OffsetDateTime.ofInstant( + Instant.ofEpochSecond(destinationBackup.getCreateTime().getSeconds(), + destinationBackup.getCreateTime().getNanos()), + ZoneId.systemDefault()), + OffsetDateTime.ofInstant( + Instant.ofEpochSecond(destinationBackup.getVersionTime().getSeconds(), + destinationBackup.getVersionTime().getNanos()), + ZoneId.systemDefault()))); } } // [END spanner_copy_backup] diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithEncryptionKey.java index b2a00ae2ad..e2c7b17061 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithEncryptionKey.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithEncryptionKey.java @@ -18,17 +18,18 @@ // [START spanner_create_backup_with_encryption_key] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Backup; -import com.google.cloud.spanner.BackupId; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.encryption.EncryptionConfigs; -import com.google.spanner.admin.database.v1.CreateBackupMetadata; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.protobuf.Timestamp; +import com.google.spanner.admin.database.v1.Backup; +import com.google.spanner.admin.database.v1.BackupName; +import com.google.spanner.admin.database.v1.CreateBackupEncryptionConfig; +import com.google.spanner.admin.database.v1.CreateBackupEncryptionConfig.EncryptionType; +import com.google.spanner.admin.database.v1.CreateBackupRequest; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.InstanceName; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -37,7 +38,7 @@ public class CreateBackupWithEncryptionKey { - static void createBackupWithEncryptionKey() throws InterruptedException { + static void createBackupWithEncryptionKey() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; String instanceId = "my-instance"; @@ -47,8 +48,8 @@ static void createBackupWithEncryptionKey() throws InterruptedException { "projects/" + projectId + "/locations//keyRings//cryptoKeys/"; try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { createBackupWithEncryptionKey( adminClient, projectId, @@ -60,24 +61,29 @@ static void createBackupWithEncryptionKey() throws InterruptedException { } static Void createBackupWithEncryptionKey(DatabaseAdminClient adminClient, - String projectId, String instanceId, String databaseId, String backupId, String kmsKeyName) - throws InterruptedException { + String projectId, String instanceId, String databaseId, String backupId, String kmsKeyName) { // Set expire time to 14 days from now. - final Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS)); - final Backup backupToCreate = adminClient - .newBackupBuilder(BackupId.of(projectId, instanceId, backupId)) - .setDatabase(DatabaseId.of(projectId, instanceId, databaseId)) - .setExpireTime(expireTime) - .setEncryptionConfig(EncryptionConfigs.customerManagedEncryption(kmsKeyName)) - .build(); - final OperationFuture operation = adminClient - .createBackup(backupToCreate); + final Timestamp expireTime = + Timestamp.newBuilder().setSeconds(TimeUnit.MILLISECONDS.toSeconds(( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14)))).build(); + final BackupName backupName = BackupName.of(projectId, instanceId, backupId); + Backup backup = Backup.newBuilder() + .setName(backupName.toString()) + .setDatabase(DatabaseName.of(projectId, instanceId, databaseId).toString()) + .setExpireTime(expireTime).build(); - Backup backup; + final CreateBackupRequest request = + CreateBackupRequest.newBuilder() + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setBackupId(backupId) + .setBackup(backup) + .setEncryptionConfig( + CreateBackupEncryptionConfig.newBuilder() + .setEncryptionType(EncryptionType.CUSTOMER_MANAGED_ENCRYPTION) + .setKmsKeyName(kmsKeyName).build()).build(); try { System.out.println("Waiting for operation to complete..."); - backup = operation.get(1200, TimeUnit.SECONDS); + backup = adminClient.createBackupAsync(request).get(1200, TimeUnit.SECONDS); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw SpannerExceptionFactory.asSpannerException(e.getCause()); @@ -89,14 +95,13 @@ static Void createBackupWithEncryptionKey(DatabaseAdminClient adminClient, // If the operation timed out propagates the timeout throw SpannerExceptionFactory.propagateTimeout(e); } - System.out.printf( "Backup %s of size %d bytes was created at %s using encryption key %s%n", - backup.getId().getName(), - backup.getSize(), + backup.getName(), + backup.getSizeBytes(), LocalDateTime.ofEpochSecond( - backup.getProto().getCreateTime().getSeconds(), - backup.getProto().getCreateTime().getNanos(), + backup.getCreateTime().getSeconds(), + backup.getCreateTime().getNanos(), OffsetDateTime.now().getOffset()), kmsKeyName ); diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSample.java b/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSample.java index fa3354dd9c..33917685cd 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSample.java @@ -1,11 +1,11 @@ /* - * Copyright 2021 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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,60 +18,51 @@ //[START spanner_create_database_with_default_leader] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; -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.spanner.admin.database.v1.CreateDatabaseMetadata; -import java.util.Arrays; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.Database; +import java.io.IOException; import java.util.concurrent.ExecutionException; public class CreateDatabaseWithDefaultLeaderSample { - static void createDatabaseWithDefaultLeader() { + static void createDatabaseWithDefaultLeader() 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"; + final String instanceName = "projects/my-project/instances/my-instance-id"; + final String databaseId = "my-database-name"; final String defaultLeader = "my-default-leader"; - createDatabaseWithDefaultLeader(projectId, instanceId, databaseId, defaultLeader); + createDatabaseWithDefaultLeader(instanceName, databaseId, defaultLeader); } - static void createDatabaseWithDefaultLeader( - String projectId, String instanceId, String databaseId, String defaultLeader) { - try (Spanner spanner = SpannerOptions - .newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); - final OperationFuture operation = databaseAdminClient - .createDatabase( - instanceId, - databaseId, - Arrays.asList( - "CREATE TABLE Singers (" - + " SingerId INT64 NOT NULL," - + " FirstName STRING(1024)," - + " LastName STRING(1024)," - + " SingerInfo BYTES(MAX)" - + ") PRIMARY KEY (SingerId)", - "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", - "ALTER DATABASE " + "`" + databaseId + "`" - + " SET OPTIONS ( default_leader = '" + defaultLeader + "' )" - ) - ); - final Database database = operation.get(); - System.out.println("Created database [" + database.getId() + "]"); - System.out.println("\tDefault leader: " + database.getDefaultLeader()); + static void createDatabaseWithDefaultLeader(String instanceName, String databaseId, + String defaultLeader) throws IOException { + try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) { + Database createdDatabase = + databaseAdminClient.createDatabaseAsync( + CreateDatabaseRequest.newBuilder() + .setParent(instanceName) + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .addAllExtraStatements( + ImmutableList.of("CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)", + "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", + "ALTER DATABASE " + "`" + databaseId + "`" + + " SET OPTIONS ( default_leader = '" + defaultLeader + "' )")) + .build()).get(); + System.out.println("Created database [" + createdDatabase.getName() + "]"); + System.out.println("\tDefault leader: " + createdDatabase.getDefaultLeader()); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -82,4 +73,4 @@ static void createDatabaseWithDefaultLeader( } } } -//[END spanner_create_database_with_default_leader] +//[END spanner_create_database_with_default_leader] \ No newline at end of file diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithEncryptionKey.java index 7d3850933b..c06e9c3eba 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithEncryptionKey.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithEncryptionKey.java @@ -18,16 +18,15 @@ // [START spanner_create_database_with_encryption_key] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.encryption.EncryptionConfigs; -import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; -import java.util.Arrays; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.EncryptionConfig; +import com.google.spanner.admin.database.v1.InstanceName; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -43,8 +42,8 @@ static void createDatabaseWithEncryptionKey() { "projects/" + projectId + "/locations//keyRings//cryptoKeys/"; try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { createDatabaseWithEncryptionKey( adminClient, projectId, @@ -56,32 +55,35 @@ static void createDatabaseWithEncryptionKey() { static void createDatabaseWithEncryptionKey(DatabaseAdminClient adminClient, String projectId, String instanceId, String databaseId, String kmsKeyName) { - final Database databaseToCreate = adminClient - .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) - .setEncryptionConfig(EncryptionConfigs.customerManagedEncryption(kmsKeyName)) + InstanceName instanceName = InstanceName.of(projectId, instanceId); + CreateDatabaseRequest request = CreateDatabaseRequest.newBuilder() + .setParent(instanceName.toString()) + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .setEncryptionConfig(EncryptionConfig.newBuilder().setKmsKeyName(kmsKeyName).build()) + .addAllExtraStatements( + ImmutableList.of( + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)", + "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" + )) .build(); - final OperationFuture operation = adminClient - .createDatabase(databaseToCreate, Arrays.asList( - "CREATE TABLE Singers (" - + " SingerId INT64 NOT NULL," - + " FirstName STRING(1024)," - + " LastName STRING(1024)," - + " SingerInfo BYTES(MAX)" - + ") PRIMARY KEY (SingerId)", - "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" - )); try { System.out.println("Waiting for operation to complete..."); - Database createdDatabase = operation.get(120, TimeUnit.SECONDS); + Database createdDatabase = + adminClient.createDatabaseAsync(request).get(120, TimeUnit.SECONDS); System.out.printf( "Database %s created with encryption key %s%n", - createdDatabase.getId(), + createdDatabase.getName(), createdDatabase.getEncryptionConfig().getKmsKeyName() ); } catch (ExecutionException e) { diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSample.java b/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSample.java index 1eaa7c403d..888fe62588 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSample.java @@ -18,15 +18,15 @@ // [START spanner_create_database_with_version_retention_period] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; 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.spanner.admin.database.v1.CreateDatabaseMetadata; -import java.util.Arrays; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.common.collect.Lists; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.InstanceName; import java.util.concurrent.ExecutionException; public class CreateDatabaseWithVersionRetentionPeriodSample { @@ -38,39 +38,25 @@ static void createDatabaseWithVersionRetentionPeriod() { String databaseId = "my-database"; String versionRetentionPeriod = "7d"; - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - createDatabaseWithVersionRetentionPeriod(adminClient, instanceId, databaseId, - versionRetentionPeriod); - } + createDatabaseWithVersionRetentionPeriod(projectId, instanceId, databaseId, + versionRetentionPeriod); } - static void createDatabaseWithVersionRetentionPeriod(DatabaseAdminClient adminClient, + static void createDatabaseWithVersionRetentionPeriod(String projectId, String instanceId, String databaseId, String versionRetentionPeriod) { - OperationFuture op = - adminClient.createDatabase( - instanceId, - databaseId, - Arrays.asList( - "CREATE TABLE Singers (" - + " SingerId INT64 NOT NULL," - + " FirstName STRING(1024)," - + " LastName STRING(1024)," - + " SingerInfo BYTES(MAX)" - + ") PRIMARY KEY (SingerId)", - "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", - "ALTER DATABASE " + "`" + databaseId + "`" - + " SET OPTIONS ( version_retention_period = '" + versionRetentionPeriod + "' )" - )); - try { - Database database = op.get(); - System.out.println("Created database [" + database.getId() + "]"); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .addAllExtraStatements(Lists.newArrayList("ALTER DATABASE " + "`" + databaseId + "`" + + " SET OPTIONS ( version_retention_period = '" + versionRetentionPeriod + "' )")) + .build(); + Database database = + databaseAdminClient.createDatabaseAsync(request).get(); + System.out.println("Created database [" + database.getName() + "]"); System.out.println("\tVersion retention period: " + database.getVersionRetentionPeriod()); System.out.println("\tEarliest version time: " + database.getEarliestVersionTime()); } catch (ExecutionException e) { diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceConfigSample.java index 379e0e2617..426d7c0484 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceConfigSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceConfigSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 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. @@ -17,53 +17,73 @@ package com.example.spanner; // [START spanner_create_instance_config] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceConfig; -import com.google.cloud.spanner.InstanceConfigId; -import com.google.cloud.spanner.InstanceConfigInfo; -import com.google.cloud.spanner.ReplicaInfo; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.instance.v1.CreateInstanceConfigMetadata; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; +import com.google.spanner.admin.instance.v1.CreateInstanceConfigRequest; +import com.google.spanner.admin.instance.v1.InstanceConfig; +import com.google.spanner.admin.instance.v1.InstanceConfigName; +import com.google.spanner.admin.instance.v1.ProjectName; +import com.google.spanner.admin.instance.v1.ReplicaInfo; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; +import java.util.stream.Stream; class CreateInstanceConfigSample { + static void createInstanceConfig() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; - String baseInstanceConfig = "my-base-instance-config"; + String baseInstanceConfigId = "nam11"; String instanceConfigId = "custom-instance-config4"; - createInstanceConfig(projectId, baseInstanceConfig, instanceConfigId); + + createInstanceConfig(projectId, baseInstanceConfigId, instanceConfigId); } static void createInstanceConfig( - String projectId, String baseInstanceConfig, String instanceConfigId) { + String projectId, String baseInstanceConfigId, String instanceConfigId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); - final InstanceConfig baseConfig = instanceAdminClient.getInstanceConfig(baseInstanceConfig); - List readOnlyReplicas = - ImmutableList.of(baseConfig.getOptionalReplicas().get(0)); - InstanceConfigInfo instanceConfigInfo = - InstanceConfig.newBuilder(InstanceConfigId.of(projectId, instanceConfigId), baseConfig) - .setDisplayName(instanceConfigId) - .addReadOnlyReplicas(readOnlyReplicas) - .build(); - final OperationFuture operation = - instanceAdminClient.createInstanceConfig(instanceConfigInfo); + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { + final InstanceConfigName baseInstanceConfigName = InstanceConfigName.of(projectId, + baseInstanceConfigId); + final InstanceConfig baseConfig = + instanceAdminClient.getInstanceConfig(baseInstanceConfigName.toString()); + final InstanceConfigName instanceConfigName = InstanceConfigName.of(projectId, + instanceConfigId); + /** + * The replicas for the custom instance configuration must include all the replicas of the + * base configuration, in addition to at least one from the list of optional replicas of the + * base configuration. + */ + final List replicas = + Stream.concat(baseConfig.getReplicasList().stream(), + baseConfig.getOptionalReplicasList().stream().limit(1)).collect(Collectors.toList()); + final InstanceConfig instanceConfig = + InstanceConfig.newBuilder().setName(instanceConfigName.toString()) + .setBaseConfig(baseInstanceConfigName.toString()) + .setDisplayName("Instance Configuration").addAllReplicas(replicas).build(); + final CreateInstanceConfigRequest createInstanceConfigRequest = + CreateInstanceConfigRequest.newBuilder().setParent(ProjectName.of(projectId).toString()) + .setInstanceConfigId(instanceConfigId).setInstanceConfig(instanceConfig).build(); try { - System.out.printf("Waiting for create operation for %s to complete...\n", instanceConfigId); - InstanceConfig instanceConfig = operation.get(5, TimeUnit.MINUTES); - System.out.printf("Created instance configuration %s\n", instanceConfig.getId()); + System.out.printf("Waiting for create operation for %s to complete...\n", + instanceConfigName); + InstanceConfig instanceConfigResult = + instanceAdminClient.createInstanceConfigAsync( + createInstanceConfigRequest).get(5, TimeUnit.MINUTES); + System.out.printf("Created instance configuration %s\n", instanceConfigResult.getName()); } catch (ExecutionException | TimeoutException e) { System.out.printf( "Error: Creating instance configuration %s failed with error message %s\n", - instanceConfigInfo.getId(), e.getMessage()); + instanceConfig.getName(), e.getMessage()); } catch (InterruptedException e) { System.out.println( "Error: Waiting for createInstanceConfig operation to finish was interrupted"); diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceExample.java b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceExample.java index 44e36a8b27..b53727ba6d 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceExample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 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. @@ -17,15 +17,14 @@ package com.example.spanner; //[START spanner_create_instance] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.Instance; -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceConfigId; -import com.google.cloud.spanner.InstanceId; -import com.google.cloud.spanner.InstanceInfo; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.spanner.admin.instance.v1.CreateInstanceMetadata; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; +import com.google.spanner.admin.instance.v1.CreateInstanceRequest; +import com.google.spanner.admin.instance.v1.Instance; +import com.google.spanner.admin.instance.v1.InstanceConfigName; +import com.google.spanner.admin.instance.v1.ProjectName; import java.util.concurrent.ExecutionException; class CreateInstanceExample { @@ -38,36 +37,41 @@ static void createInstance() { } static void createInstance(String projectId, String instanceId) { - Spanner spanner = SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); - // Set Instance configuration. - String configId = "regional-us-central1"; int nodeCount = 2; String displayName = "Descriptive name"; - // Create an InstanceInfo object that will be used to create the instance. - InstanceInfo instanceInfo = - InstanceInfo.newBuilder(InstanceId.of(projectId, instanceId)) - .setInstanceConfigId(InstanceConfigId.of(projectId, configId)) - .setNodeCount(nodeCount) + // Create an Instance object that will be used to create the instance. + Instance instance = + Instance.newBuilder() .setDisplayName(displayName) + .setNodeCount(nodeCount) + .setConfig( + InstanceConfigName.of(projectId, "regional-us-central1").toString()) .build(); - OperationFuture operation = - instanceAdminClient.createInstance(instanceInfo); - try { + + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { + // Wait for the createInstance operation to finish. - Instance instance = operation.get(); - System.out.printf("Instance %s was successfully created%n", instance.getId()); + Instance createdInstance = instanceAdminClient.createInstanceAsync( + CreateInstanceRequest.newBuilder() + .setParent(ProjectName.of(projectId).toString()) + .setInstanceId(instanceId) + .setInstance(instance) + .build()).get(); + System.out.printf("Instance %s was successfully created%n", createdInstance.getName()); } catch (ExecutionException e) { System.out.printf( "Error: Creating instance %s failed with error message %s%n", - instanceInfo.getId(), e.getMessage()); + instance.getName(), e.getMessage()); } catch (InterruptedException e) { System.out.println("Error: Waiting for createInstance operation to finish was interrupted"); - } finally { - spanner.close(); } } } -//[END spanner_create_instance] +//[END spanner_create_instance] \ No newline at end of file diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithAutoscalingConfigExample.java b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithAutoscalingConfigExample.java index 0719857411..dc62dd7a68 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithAutoscalingConfigExample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithAutoscalingConfigExample.java @@ -1,5 +1,5 @@ /* - * 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. @@ -18,16 +18,14 @@ // [START spanner_create_instance_with_autoscaling_config] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.Instance; -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceConfigId; -import com.google.cloud.spanner.InstanceId; -import com.google.cloud.spanner.InstanceInfo; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; import com.google.spanner.admin.instance.v1.AutoscalingConfig; -import com.google.spanner.admin.instance.v1.CreateInstanceMetadata; +import com.google.spanner.admin.instance.v1.CreateInstanceRequest; +import com.google.spanner.admin.instance.v1.Instance; +import com.google.spanner.admin.instance.v1.InstanceConfigName; +import com.google.spanner.admin.instance.v1.ProjectName; import java.util.concurrent.ExecutionException; class CreateInstanceWithAutoscalingConfigExample { @@ -40,44 +38,55 @@ static void createInstance() { } static void createInstance(String projectId, String instanceId) { - Spanner spanner = SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { + // Set Instance configuration. + String configId = "regional-us-central1"; + String displayName = "Descriptive name"; - // Set Instance configuration. - String configId = "regional-us-central1"; - // Create an autoscaling config. - AutoscalingConfig autoscalingConfig = - AutoscalingConfig.newBuilder() - .setAutoscalingLimits( - AutoscalingConfig.AutoscalingLimits.newBuilder().setMinNodes(1).setMaxNodes(2)) - .setAutoscalingTargets( - AutoscalingConfig.AutoscalingTargets.newBuilder() - .setHighPriorityCpuUtilizationPercent(65) - .setStorageUtilizationPercent(95)) - .build(); + // Create an autoscaling config. + // When autoscaling_config is enabled, node_count and processing_units fields + // need not be specified. + AutoscalingConfig autoscalingConfig = + AutoscalingConfig.newBuilder() + .setAutoscalingLimits( + AutoscalingConfig.AutoscalingLimits.newBuilder().setMinNodes(1).setMaxNodes(2)) + .setAutoscalingTargets( + AutoscalingConfig.AutoscalingTargets.newBuilder() + .setHighPriorityCpuUtilizationPercent(65) + .setStorageUtilizationPercent(95)) + .build(); + Instance instance = + Instance.newBuilder() + .setAutoscalingConfig(autoscalingConfig) + .setDisplayName(displayName) + .setConfig( + InstanceConfigName.of(projectId, configId).toString()) + .build(); - // Create an InstanceInfo object that will be used to create the instance. - InstanceInfo instanceInfo = - InstanceInfo.newBuilder(InstanceId.of(projectId, instanceId)) - .setInstanceConfigId(InstanceConfigId.of(projectId, configId)) - .setAutoscalingConfig(autoscalingConfig) - .setDisplayName("Descriptive name") - .build(); - OperationFuture operation = - instanceAdminClient.createInstance(instanceInfo); - - try { - // Wait for the createInstance operation to finish. - Instance instance = operation.get(); - System.out.printf("Autoscaler instance %s was successfully created%n", instance.getId()); - } catch (ExecutionException e) { - System.out.printf( - "Error: Creating instance %s failed with error message %s%n", - instanceInfo.getId(), e.getMessage()); - } catch (InterruptedException e) { - System.out.println("Error: Waiting for createInstance operation to finish was interrupted"); - } finally { - spanner.close(); + // Creates a new instance + System.out.printf("Creating instance %s.%n", instanceId); + try { + // Wait for the createInstance operation to finish. + Instance instanceResult = instanceAdminClient.createInstanceAsync( + CreateInstanceRequest.newBuilder() + .setParent(ProjectName.of(projectId).toString()) + .setInstanceId(instanceId) + .setInstance(instance) + .build()).get(); + System.out.printf("Autoscaler instance %s was successfully created%n", + instanceResult.getName()); + } catch (ExecutionException e) { + System.out.printf( + "Error: Creating instance %s failed with error message %s%n", + instance.getName(), e.getMessage()); + } catch (InterruptedException e) { + System.out.println("Error: Waiting for createInstance operation to finish was interrupted"); + } } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithProcessingUnitsExample.java b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithProcessingUnitsExample.java index 1bfc66d3fd..293c10249c 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithProcessingUnitsExample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithProcessingUnitsExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 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. @@ -18,15 +18,13 @@ //[START spanner_create_instance_with_processing_units] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.Instance; -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceConfigId; -import com.google.cloud.spanner.InstanceId; -import com.google.cloud.spanner.InstanceInfo; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.spanner.admin.instance.v1.CreateInstanceMetadata; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; +import com.google.spanner.admin.instance.v1.CreateInstanceRequest; +import com.google.spanner.admin.instance.v1.Instance; +import com.google.spanner.admin.instance.v1.InstanceConfigName; +import com.google.spanner.admin.instance.v1.ProjectName; class CreateInstanceWithProcessingUnitsExample { @@ -38,39 +36,45 @@ static void createInstance() { } static void createInstance(String projectId, String instanceId) { - Spanner spanner = SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - // Set Instance configuration. - String configId = "regional-us-central1"; - // This will create an instance with the processing power of 0.2 nodes. - int processingUnits = 500; - String displayName = "Descriptive name"; + // Set Instance configuration. + String configId = "regional-us-central1"; + // This will create an instance with the processing power of 0.2 nodes. + int processingUnits = 500; + String displayName = "Descriptive name"; - try { - // Creates a new instance - System.out.printf("Creating instance %s.%n", instanceId); - OperationFuture operation = - instanceAdminClient.createInstance(InstanceInfo - .newBuilder(InstanceId.of(projectId, instanceId)) - .setInstanceConfigId(InstanceConfigId.of(projectId, configId)) - .setProcessingUnits(processingUnits) - .setDisplayName(displayName) - .build()); + try { + // Creates a new instance + System.out.printf("Creating instance %s.%n", instanceId); + Instance instance = + Instance.newBuilder() + .setDisplayName(displayName) + .setProcessingUnits(processingUnits) + .setConfig( + InstanceConfigName.of(projectId, configId).toString()) + .build(); + // Wait for the createInstance operation to finish. + System.out.printf("Waiting for operation on %s to complete...%n", instanceId); + Instance createdInstance = instanceAdminClient.createInstanceAsync( + CreateInstanceRequest.newBuilder() + .setParent(ProjectName.of(projectId).toString()) + .setInstanceId(instanceId) + .setInstance(instance) + .build()).get(); - // Wait for the createInstance operation to finish. - System.out.printf("Waiting for operation on %s to complete...%n", instanceId); - Instance createdInstance = operation.get(); - - System.out.printf("Created instance %s.%n", createdInstance.getId().getInstance()); - - Instance instance = instanceAdminClient.getInstance(instanceId); - System.out.printf("Instance %s has %d processing units.%n", instance.getId().getInstance(), - instance.getProcessingUnits()); - } catch (Exception e) { - System.out.printf("Error: %s.%n", e.getMessage()); + System.out.printf("Created instance %s.%n", createdInstance.getName()); + System.out.printf("Instance %s has %d processing units.%n", createdInstance.getName(), + createdInstance.getProcessingUnits()); + } catch (Exception e) { + System.out.printf("Error: %s.%n", e.getMessage()); + } } - spanner.close(); } } //[END spanner_create_instance_with_processing_units] diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/CreateSequenceSample.java index 964b245ed8..757921080d 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateSequenceSample.java @@ -17,7 +17,7 @@ package com.example.spanner; // [START spanner_create_sequence] -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ResultSet; @@ -25,13 +25,16 @@ 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.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class CreateSequenceSample { + static void createSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -41,20 +44,18 @@ static void createSequence() { } static void createSequence(String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - dbAdminClient - .updateDatabaseDdl( - instanceId, - databaseId, + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + databaseAdminClient + .updateDatabaseDdlAsync( + DatabaseName.of(projectId, instanceId, databaseId), ImmutableList.of( "CREATE SEQUENCE Seq OPTIONS (sequence_kind = 'bit_reversed_positive')", "CREATE TABLE Customers (CustomerId INT64 DEFAULT " + "(GET_NEXT_SEQUENCE_VALUE(SEQUENCE Seq)), CustomerName STRING(1024)) " - + "PRIMARY KEY (CustomerId)"), - null) + + "PRIMARY KEY (CustomerId)")) .get(5, TimeUnit.MINUTES); System.out.println( diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSample.java b/samples/snippets/src/main/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSample.java index dda09591ee..c9484916a4 100644 --- a/samples/snippets/src/main/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSample.java @@ -17,10 +17,12 @@ package com.example.spanner; // [START spanner_create_table_with_foreign_key_delete_cascade] -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.DatabaseName; class CreateTableWithForeignKeyDeleteCascadeSample { @@ -30,37 +32,35 @@ static void createForeignKeyDeleteCascadeConstraint() { String instanceId = "my-instance"; String databaseId = "my-database"; - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - createForeignKeyDeleteCascadeConstraint(adminClient, instanceId, databaseId); - } + createForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId); } static void createForeignKeyDeleteCascadeConstraint( - DatabaseAdminClient adminClient, String instanceId, String databaseId) { - adminClient.updateDatabaseDdl( - instanceId, - databaseId, - ImmutableList.of( - "CREATE TABLE Customers (\n" - + " CustomerId INT64 NOT NULL,\n" - + " CustomerName STRING(62) NOT NULL,\n" - + " ) PRIMARY KEY (CustomerId)", - "CREATE TABLE ShoppingCarts (\n" - + " CartId INT64 NOT NULL,\n" - + " CustomerId INT64 NOT NULL,\n" - + " CustomerName STRING(62) NOT NULL,\n" - + " CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId)\n" - + " REFERENCES Customers (CustomerId) ON DELETE CASCADE\n" - + " ) PRIMARY KEY (CartId)\n"), - null); + String projectId, String instanceId, String databaseId) { + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + databaseAdminClient.updateDatabaseDdlAsync( + DatabaseName.of(projectId, instanceId, databaseId), + ImmutableList.of( + "CREATE TABLE Customers (\n" + + " CustomerId INT64 NOT NULL,\n" + + " CustomerName STRING(62) NOT NULL,\n" + + " ) PRIMARY KEY (CustomerId)", + "CREATE TABLE ShoppingCarts (\n" + + " CartId INT64 NOT NULL,\n" + + " CustomerId INT64 NOT NULL,\n" + + " CustomerName STRING(62) NOT NULL,\n" + + " CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId)\n" + + " REFERENCES Customers (CustomerId) ON DELETE CASCADE\n" + + " ) PRIMARY KEY (CartId)\n")); - System.out.printf( - String.format( - "Created Customers and ShoppingCarts table with FKShoppingCartsCustomerId\n" - + "foreign key constraint on database %s on instance %s\n", - databaseId, instanceId)); + System.out.printf( + String.format( + "Created Customers and ShoppingCarts table with FKShoppingCartsCustomerId\n" + + "foreign key constraint on database %s on instance %s\n", + databaseId, instanceId)); + } } } // [END spanner_create_table_with_foreign_key_delete_cascade] diff --git a/samples/snippets/src/main/java/com/example/spanner/DeleteInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/DeleteInstanceConfigSample.java index de76673ca7..c2da7b3000 100644 --- a/samples/snippets/src/main/java/com/example/spanner/DeleteInstanceConfigSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/DeleteInstanceConfigSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 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. @@ -17,12 +17,16 @@ package com.example.spanner; // [START spanner_delete_instance_config] -import com.google.cloud.spanner.InstanceAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; +import com.google.spanner.admin.instance.v1.DeleteInstanceConfigRequest; +import com.google.spanner.admin.instance.v1.InstanceConfigName; class DeleteInstanceConfigSample { + static void deleteInstanceConfig() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; @@ -32,16 +36,24 @@ static void deleteInstanceConfig() { static void deleteInstanceConfig(String projectId, String instanceConfigId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { + final InstanceConfigName instanceConfigName = InstanceConfigName.of(projectId, + instanceConfigId); + final DeleteInstanceConfigRequest request = + DeleteInstanceConfigRequest.newBuilder().setName(instanceConfigName.toString()).build(); + try { - System.out.printf("Deleting %s...\n", instanceConfigId); - instanceAdminClient.deleteInstanceConfig(instanceConfigId); - System.out.printf("Deleted instance configuration %s\n", instanceConfigId); + System.out.printf("Deleting %s...\n", instanceConfigName); + instanceAdminClient.deleteInstanceConfig(request); + System.out.printf("Deleted instance configuration %s\n", instanceConfigName); } catch (SpannerException e) { System.out.printf( "Error: Deleting instance configuration %s failed with error message: %s\n", - instanceConfigId, e.getMessage()); + instanceConfigName, e.getMessage()); } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/DropForeignKeyConstraintDeleteCascadeSample.java b/samples/snippets/src/main/java/com/example/spanner/DropForeignKeyConstraintDeleteCascadeSample.java index 13f39d129f..7c35b9f621 100644 --- a/samples/snippets/src/main/java/com/example/spanner/DropForeignKeyConstraintDeleteCascadeSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/DropForeignKeyConstraintDeleteCascadeSample.java @@ -17,10 +17,12 @@ package com.example.spanner; // [START spanner_drop_foreign_key_constraint_delete_cascade] -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.DatabaseName; class DropForeignKeyConstraintDeleteCascadeSample { @@ -30,28 +32,26 @@ static void deleteForeignKeyDeleteCascadeConstraint() { String instanceId = "my-instance"; String databaseId = "my-database"; - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - deleteForeignKeyDeleteCascadeConstraint(adminClient, instanceId, databaseId); - } + deleteForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId); } static void deleteForeignKeyDeleteCascadeConstraint( - DatabaseAdminClient adminClient, String instanceId, String databaseId) { - adminClient.updateDatabaseDdl( - instanceId, - databaseId, - ImmutableList.of( - "ALTER TABLE ShoppingCarts\n" - + " DROP CONSTRAINT FKShoppingCartsCustomerName\n"), - null); - - System.out.printf( - String.format( - "Altered ShoppingCarts table to drop FKShoppingCartsCustomerName\n" - + "foreign key constraint on database %s on instance %s\n", - databaseId, instanceId)); + String projectId, String instanceId, String databaseId) { + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + databaseAdminClient.updateDatabaseDdlAsync( + DatabaseName.of(projectId, instanceId, databaseId), + ImmutableList.of( + "ALTER TABLE ShoppingCarts\n" + + " DROP CONSTRAINT FKShoppingCartsCustomerName\n")); + + System.out.printf( + String.format( + "Altered ShoppingCarts table to drop FKShoppingCartsCustomerName\n" + + "foreign key constraint on database %s on instance %s\n", + databaseId, instanceId)); + } } } // [END spanner_drop_foreign_key_constraint_delete_cascade] diff --git a/samples/snippets/src/main/java/com/example/spanner/DropSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/DropSequenceSample.java index 6d054eea4d..9f1b32caed 100644 --- a/samples/snippets/src/main/java/com/example/spanner/DropSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/DropSequenceSample.java @@ -17,16 +17,19 @@ package com.example.spanner; // [START spanner_drop_sequence] -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.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class DropSequenceSample { + static void dropSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -37,19 +40,14 @@ static void dropSequence() { static void dropSequence(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - - dbAdminClient - .updateDatabaseDdl( - instanceId, - databaseId, + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + databaseAdminClient + .updateDatabaseDdlAsync(DatabaseName.of(projectId, instanceId, databaseId), ImmutableList.of( "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", - "DROP SEQUENCE Seq"), - null) + "DROP SEQUENCE Seq")) .get(5, TimeUnit.MINUTES); - System.out.println( "Altered Customers table to drop DEFAULT from CustomerId column " + "and dropped the Seq sequence"); diff --git a/samples/snippets/src/main/java/com/example/spanner/EnableFineGrainedAccess.java b/samples/snippets/src/main/java/com/example/spanner/EnableFineGrainedAccess.java index c4c17645b6..e4e35bd95a 100644 --- a/samples/snippets/src/main/java/com/example/spanner/EnableFineGrainedAccess.java +++ b/samples/snippets/src/main/java/com/example/spanner/EnableFineGrainedAccess.java @@ -17,13 +17,18 @@ package com.example.spanner; // [START spanner_enable_fine_grained_access] -import com.google.cloud.Binding; -import com.google.cloud.Condition; -import com.google.cloud.Policy; -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; +import com.google.iam.v1.Binding; +import com.google.iam.v1.GetIamPolicyRequest; +import com.google.iam.v1.GetPolicyOptions; +import com.google.iam.v1.Policy; +import com.google.iam.v1.SetIamPolicyRequest; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.type.Expr; public class EnableFineGrainedAccess { @@ -46,12 +51,15 @@ static void enableFineGrainedAccess( String title, String role) { try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - Policy policy = adminClient.getDatabaseIAMPolicy(instanceId, databaseId, 3); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + final GetPolicyOptions options = + GetPolicyOptions.newBuilder().setRequestedPolicyVersion(3).build(); + final GetIamPolicyRequest getRequest = + GetIamPolicyRequest.newBuilder() + .setResource(DatabaseName.of(projectId, instanceId, databaseId).toString()) + .setOptions(options).build(); + final Policy policy = databaseAdminClient.getIamPolicy(getRequest); int policyVersion = policy.getVersion(); // The policy in the response from getDatabaseIAMPolicy might use the policy version // that you specified, or it might use a lower policy version. For example, if you @@ -65,20 +73,17 @@ static void enableFineGrainedAccess( Binding binding1 = Binding.newBuilder() .setRole("roles/spanner.fineGrainedAccessUser") - .setMembers(ImmutableList.of(iamMember)) + .addAllMembers(ImmutableList.of(iamMember)) .build(); Binding binding2 = Binding.newBuilder() .setRole("roles/spanner.databaseRoleUser") .setCondition( - Condition.newBuilder() - .setDescription(title) - .setExpression( - String.format("resource.name.endsWith(\"/databaseRoles/%s\")", role)) - .setTitle(title) - .build()) - .setMembers(ImmutableList.of(iamMember)) + Expr.newBuilder().setDescription(title).setExpression( + String.format("resource.name.endsWith(\"/databaseRoles/%s\")", role) + ).setTitle(title).build()) + .addAllMembers(ImmutableList.of(iamMember)) .build(); ImmutableList bindings = ImmutableList.builder() @@ -90,10 +95,13 @@ static void enableFineGrainedAccess( Policy.newBuilder() .setVersion(policyVersion) .setEtag(policy.getEtag()) - .setBindings(bindings) + .addAllBindings(bindings) .build(); - Policy response = - adminClient.setDatabaseIAMPolicy(instanceId, databaseId, policyWithConditions); + final SetIamPolicyRequest setRequest = + SetIamPolicyRequest.newBuilder() + .setResource(DatabaseName.of(projectId, instanceId, databaseId).toString()) + .setPolicy(policyWithConditions).build(); + final Policy response = databaseAdminClient.setIamPolicy(setRequest); System.out.printf( "Enabled fine-grained access in IAM with version %d%n", response.getVersion()); } diff --git a/samples/snippets/src/main/java/com/example/spanner/GetDatabaseDdlSample.java b/samples/snippets/src/main/java/com/example/spanner/GetDatabaseDdlSample.java index 93d32a5ec6..b84f1c0ccc 100644 --- a/samples/snippets/src/main/java/com/example/spanner/GetDatabaseDdlSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/GetDatabaseDdlSample.java @@ -18,10 +18,11 @@ //[START spanner_get_database_ddl] -import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import java.util.List; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.GetDatabaseDdlResponse; public class GetDatabaseDdlSample { @@ -35,15 +36,13 @@ static void getDatabaseDdl() { static void getDatabaseDdl( String projectId, String instanceId, String databaseId) { - try (Spanner spanner = SpannerOptions - .newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); - final List ddls = databaseAdminClient.getDatabaseDdl(instanceId, databaseId); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + final GetDatabaseDdlResponse response = + databaseAdminClient.getDatabaseDdl(DatabaseName.of(projectId, instanceId, databaseId)); System.out.println("Retrieved database DDL for " + databaseId); - for (String ddl : ddls) { + for (String ddl : response.getStatementsList()) { System.out.println(ddl); } } diff --git a/samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java index 46f38b84d1..9dd8690f75 100644 --- a/samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 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. @@ -18,35 +18,38 @@ //[START spanner_get_instance_config] -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceConfig; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; +import com.google.spanner.admin.instance.v1.InstanceConfig; +import com.google.spanner.admin.instance.v1.InstanceConfigName; public class GetInstanceConfigSample { static void getInstanceConfig() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; - final String instanceConfigName = "nam6"; - getInstanceConfig(projectId, instanceConfigName); + final String instanceConfigId = "nam6"; + getInstanceConfig(projectId, instanceConfigId); } - static void getInstanceConfig(String projectId, String instanceConfigName) { - try (Spanner spanner = SpannerOptions - .newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + static void getInstanceConfig(String projectId, String instanceConfigId) { + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { + final InstanceConfigName instanceConfigName = InstanceConfigName.of(projectId, + instanceConfigId); - final InstanceConfig instanceConfig = instanceAdminClient - .getInstanceConfig(instanceConfigName); + final InstanceConfig instanceConfig = + instanceAdminClient.getInstanceConfig(instanceConfigName.toString()); System.out.printf( "Available leader options for instance config %s: %s%n", - instanceConfig.getId(), - instanceConfig.getLeaderOptions() + instanceConfig.getName(), + instanceConfig.getLeaderOptionsList() ); } } diff --git a/samples/snippets/src/main/java/com/example/spanner/ListDatabaseRoles.java b/samples/snippets/src/main/java/com/example/spanner/ListDatabaseRoles.java index 9292405054..e16a55cb7b 100644 --- a/samples/snippets/src/main/java/com/example/spanner/ListDatabaseRoles.java +++ b/samples/snippets/src/main/java/com/example/spanner/ListDatabaseRoles.java @@ -17,16 +17,18 @@ package com.example.spanner; // [START spanner_list_database_roles] -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.DatabaseRole; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import java.util.concurrent.ExecutionException; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabaseRolesPage; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabaseRolesPagedResponse; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.DatabaseRole; public class ListDatabaseRoles { - static void listDatabaseRoles() throws InterruptedException, ExecutionException { + static void listDatabaseRoles() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; String instanceId = "my-instance"; @@ -36,15 +38,16 @@ static void listDatabaseRoles() throws InterruptedException, ExecutionException static void listDatabaseRoles(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); - String databasePath = DatabaseId.of(projectId, instanceId, databaseId).getName(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + DatabaseName databaseName = DatabaseName.of(projectId, instanceId, databaseId); + ListDatabaseRolesPagedResponse response + = databaseAdminClient.listDatabaseRoles(databaseName); System.out.println("List of Database roles"); - for (DatabaseRole role : adminClient.listDatabaseRoles(instanceId, databaseId).iterateAll()) { - System.out.printf("%s%n", role.getName()); + for (ListDatabaseRolesPage page : response.iteratePages()) { + for (DatabaseRole role : page.iterateAll()) { + System.out.printf("Obtained role %s%n", role.getName()); + } } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java b/samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java index 6e6a246a30..631b72dc11 100644 --- a/samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java @@ -18,11 +18,13 @@ //[START spanner_list_databases] -import com.google.api.gax.paging.Page; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabasesPage; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabasesPagedResponse; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.InstanceName; public class ListDatabasesSample { @@ -34,21 +36,20 @@ static void listDatabases() { } static void listDatabases(String projectId, String instanceId) { - try (Spanner spanner = SpannerOptions - .newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); - Page page = databaseAdminClient.listDatabases(instanceId); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + ListDatabasesPagedResponse response = + databaseAdminClient.listDatabases(InstanceName.of(projectId, instanceId)); + System.out.println("Databases for projects/" + projectId + "/instances/" + instanceId); - while (page != null) { + + for (ListDatabasesPage page : response.iteratePages()) { for (Database database : page.iterateAll()) { final String defaultLeader = database.getDefaultLeader().equals("") ? "" : "(default leader = " + database.getDefaultLeader() + ")"; - System.out.println("\t" + database.getId() + " " + defaultLeader); + System.out.println("\t" + database.getName() + " " + defaultLeader); } - page = page.getNextPage(); } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigOperationsSample.java b/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigOperationsSample.java index bcf68b7d58..b42c52126b 100644 --- a/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigOperationsSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigOperationsSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 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. @@ -17,15 +17,18 @@ package com.example.spanner; // [START spanner_list_instance_config_operations] -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.Options; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; import com.google.longrunning.Operation; import com.google.protobuf.InvalidProtocolBufferException; import com.google.spanner.admin.instance.v1.CreateInstanceConfigMetadata; +import com.google.spanner.admin.instance.v1.ListInstanceConfigOperationsRequest; +import com.google.spanner.admin.instance.v1.ProjectName; public class ListInstanceConfigOperationsSample { + static void listInstanceConfigOperations() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; @@ -34,32 +37,36 @@ static void listInstanceConfigOperations() { static void listInstanceConfigOperations(String projectId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); - - try { - System.out.printf( - "Getting list of instance config operations for project %s...\n", - projectId); - final Iterable instanceConfigOperations = - instanceAdminClient - .listInstanceConfigOperations( - Options.filter( - "(metadata.@type=type.googleapis.com/" - + "google.spanner.admin.instance.v1.CreateInstanceConfigMetadata)")) - .iterateAll(); - for (Operation operation : instanceConfigOperations) { - CreateInstanceConfigMetadata metadata = - operation.getMetadata().unpack(CreateInstanceConfigMetadata.class); - System.out.printf( - "Create instance config operation for %s is %d%% completed.\n", - metadata.getInstanceConfig().getName(), metadata.getProgress().getProgressPercent()); - } - } catch (InvalidProtocolBufferException e) { + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { + final ProjectName projectName = ProjectName.of(projectId); + System.out.printf( + "Getting list of instance config operations for project %s...\n", + projectId); + final ListInstanceConfigOperationsRequest request = + ListInstanceConfigOperationsRequest.newBuilder() + .setParent(projectName.toString()) + .setFilter("(metadata.@type=type.googleapis.com/" + + "google.spanner.admin.instance.v1.CreateInstanceConfigMetadata)").build(); + final Iterable instanceConfigOperations = + instanceAdminClient.listInstanceConfigOperations(request).iterateAll(); + for (Operation operation : instanceConfigOperations) { + CreateInstanceConfigMetadata metadata = + operation.getMetadata().unpack(CreateInstanceConfigMetadata.class); System.out.printf( - "Error: Listing instance config operations failed with error message %s\n", - e.getMessage()); + "Create instance config operation for %s is %d%% completed.\n", + metadata.getInstanceConfig().getName(), metadata.getProgress().getProgressPercent()); } + System.out.printf( + "Obtained list of instance config operations for project %s...\n", + projectName); + } catch (InvalidProtocolBufferException e) { + System.out.printf( + "Error: Listing instance config operations failed with error message %s\n", + e.getMessage()); } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java b/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java index d0de12dfce..7c5391638b 100644 --- a/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 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. @@ -18,32 +18,34 @@ //[START spanner_list_instance_configs] -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceConfig; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; +import com.google.spanner.admin.instance.v1.InstanceConfig; +import com.google.spanner.admin.instance.v1.ProjectName; public class ListInstanceConfigsSample { static void listInstanceConfigs() { // TODO(developer): Replace these variables before running the sample. - final String projectId = "my-project"; + String projectId = "my-project"; listInstanceConfigs(projectId); } static void listInstanceConfigs(String projectId) { - try (Spanner spanner = SpannerOptions - .newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); - - for (InstanceConfig instanceConfig : instanceAdminClient.listInstanceConfigs().iterateAll()) { + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { + final ProjectName projectName = ProjectName.of(projectId); + for (InstanceConfig instanceConfig : + instanceAdminClient.listInstanceConfigs(projectName).iterateAll()) { System.out.printf( "Available leader options for instance config %s: %s%n", - instanceConfig.getId(), - instanceConfig.getLeaderOptions() + instanceConfig.getName(), + instanceConfig.getLeaderOptionsList() ); } } diff --git a/samples/snippets/src/main/java/com/example/spanner/PgAlterSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/PgAlterSequenceSample.java index e10c29807f..a3e4a9a677 100644 --- a/samples/snippets/src/main/java/com/example/spanner/PgAlterSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/PgAlterSequenceSample.java @@ -17,7 +17,7 @@ package com.example.spanner; // [START spanner_postgresql_alter_sequence] -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ResultSet; @@ -25,13 +25,16 @@ 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.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class PgAlterSequenceSample { + static void pgAlterSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -42,14 +45,13 @@ static void pgAlterSequence() { static void pgAlterSequence(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - dbAdminClient - .updateDatabaseDdl( - instanceId, - databaseId, - ImmutableList.of("ALTER SEQUENCE Seq SKIP RANGE 1000 5000000"), - null) + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + + databaseAdminClient + .updateDatabaseDdlAsync( + DatabaseName.of(projectId, instanceId, databaseId), + ImmutableList.of("ALTER SEQUENCE Seq SKIP RANGE 1000 5000000")) .get(5, TimeUnit.MINUTES); System.out.println( "Altered Seq sequence to skip an inclusive range between 1000 and 5000000"); diff --git a/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java b/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java index d76b26b178..abebdef39a 100644 --- a/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java +++ b/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java @@ -18,8 +18,6 @@ // [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; @@ -28,7 +26,9 @@ 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 com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.common.collect.Lists; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.Collections; import java.util.concurrent.ExecutionException; @@ -43,34 +43,28 @@ static void pgCaseSensitivity() { } static void pgCaseSensitivity(String projectId, String instanceId, String databaseId) { + try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { // 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(); + databaseAdminClient.updateDatabaseDdlAsync( + DatabaseName.of(projectId, instanceId, databaseId), + Lists.newArrayList( + "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" + + ")")).get(); DatabaseClient client = spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); diff --git a/samples/snippets/src/main/java/com/example/spanner/PgCreateSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/PgCreateSequenceSample.java index e6e23f49b8..79445aa272 100644 --- a/samples/snippets/src/main/java/com/example/spanner/PgCreateSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/PgCreateSequenceSample.java @@ -17,7 +17,7 @@ package com.example.spanner; // [START spanner_postgresql_create_sequence] -import com.google.cloud.spanner.DatabaseAdminClient; + import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ResultSet; @@ -25,13 +25,16 @@ 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.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class PgCreateSequenceSample { + static void pgCreateSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -42,22 +45,18 @@ static void pgCreateSequence() { static void pgCreateSequence(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - - dbAdminClient - .updateDatabaseDdl( - instanceId, - databaseId, + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + databaseAdminClient + .updateDatabaseDdlAsync(DatabaseName.of(projectId, instanceId, databaseId).toString(), ImmutableList.of( "CREATE SEQUENCE Seq BIT_REVERSED_POSITIVE;", "CREATE TABLE Customers (CustomerId BIGINT DEFAULT nextval('Seq'), " - + "CustomerName character varying(1024), PRIMARY KEY (CustomerId))"), - null) + + "CustomerName character varying(1024), PRIMARY KEY (CustomerId))")) .get(5, TimeUnit.MINUTES); System.out.println( - "Created Seq sequence and Customers table, where its key column " + "Created Seq sequence and Customers table, where the key column " + "CustomerId uses the sequence as a default value"); final DatabaseClient dbClient = diff --git a/samples/snippets/src/main/java/com/example/spanner/PgDropSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/PgDropSequenceSample.java index c0990c1c4d..129009e9b2 100644 --- a/samples/snippets/src/main/java/com/example/spanner/PgDropSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/PgDropSequenceSample.java @@ -17,16 +17,19 @@ package com.example.spanner; // [START spanner_postgresql_drop_sequence] -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.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class PgDropSequenceSample { + static void pgDropSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -36,17 +39,16 @@ static void pgDropSequence() { } static void pgDropSequence(String projectId, String instanceId, String databaseId) { + try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - dbAdminClient - .updateDatabaseDdl( - instanceId, - databaseId, + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + databaseAdminClient + .updateDatabaseDdlAsync( + DatabaseName.of(projectId, instanceId, databaseId), ImmutableList.of( "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", - "DROP SEQUENCE Seq"), - null) + "DROP SEQUENCE Seq")) .get(5, TimeUnit.MINUTES); System.out.println( "Altered Customers table to drop DEFAULT from " diff --git a/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java b/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java index d79ba7b58f..30ee48ed6d 100644 --- a/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java @@ -18,12 +18,11 @@ // [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 com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.Arrays; import java.util.concurrent.ExecutionException; @@ -38,35 +37,29 @@ static void pgInterleavedTable() { } static void pgInterleavedTable(String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { // 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( + databaseAdminClient.updateDatabaseDdlAsync(DatabaseName.of(projectId, 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(); + 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")).get(); System.out.println("Created interleaved table hierarchy using PostgreSQL dialect"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. diff --git a/samples/snippets/src/main/java/com/example/spanner/PgSpannerSample.java b/samples/snippets/src/main/java/com/example/spanner/PgSpannerSample.java index 44b96d4a40..600206c148 100644 --- a/samples/snippets/src/main/java/com/example/spanner/PgSpannerSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/PgSpannerSample.java @@ -16,24 +16,16 @@ package com.example.spanner; -import com.google.api.gax.longrunning.OperationFuture; import com.google.api.gax.paging.Page; import com.google.cloud.ByteArray; import com.google.cloud.Date; import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.Instance; -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceId; import com.google.cloud.spanner.Key; import com.google.cloud.spanner.KeyRange; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options; import com.google.cloud.spanner.ReadOnlyTransaction; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Spanner; @@ -45,19 +37,27 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListBackupOperationsPagedResponse; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabaseOperationsPagedResponse; import com.google.common.io.BaseEncoding; import com.google.longrunning.Operation; import com.google.protobuf.InvalidProtocolBufferException; +import com.google.spanner.admin.database.v1.BackupName; +import com.google.spanner.admin.database.v1.CopyBackupMetadata; import com.google.spanner.admin.database.v1.CreateBackupMetadata; -import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.DatabaseDialect; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.ListBackupOperationsRequest; +import com.google.spanner.admin.database.v1.ListDatabaseOperationsRequest; import com.google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.admin.instance.v1.InstanceName; import com.google.spanner.v1.ExecuteSqlRequest; import java.math.BigDecimal; -import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -66,6 +66,7 @@ * Example code for using the Cloud Spanner PostgreSQL interface. */ public class PgSpannerSample { + // [START spanner_postgresql_insert_data] static final List SINGERS = Arrays.asList( @@ -83,7 +84,9 @@ public class PgSpannerSample { new Album(2, 3, "Terrified")); // [END spanner_postgresql_insert_data] - /** Class to contain performance sample data. */ + /** + * Class to contain performance sample data. + */ static class Performance { final long singerId; @@ -159,7 +162,9 @@ static class Performance { new BigDecimal("390650.99"))); // [END spanner_postgresql_insert_datatypes_data] - /** Class to contain venue sample data. */ + /** + * Class to contain venue sample data. + */ static class Venue { final long venueId; @@ -195,15 +200,18 @@ static class Venue { } // [START spanner_postgresql_create_database] - static void createPostgreSqlDatabase(DatabaseAdminClient dbAdminClient, DatabaseId id) { - OperationFuture op = dbAdminClient.createDatabase( - dbAdminClient.newDatabaseBuilder(id).setDialect(Dialect.POSTGRESQL).build(), - Collections.emptyList()); + static void createPostgreSqlDatabase( + DatabaseAdminClient dbAdminClient, String projectId, String instanceId, String databaseId) { + final CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setCreateStatement("CREATE DATABASE \"" + databaseId + "\"") + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setDatabaseDialect(DatabaseDialect.POSTGRESQL).build(); + try { // Initiate the request which returns an OperationFuture. - Database db = op.get(); - System.out.println("Created database [" + db.getId() + "]"); - createTableUsingDdl(dbAdminClient, id); + Database db = dbAdminClient.createDatabaseAsync(request).get(); + System.out.println("Created database [" + db.getName() + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -272,9 +280,9 @@ static void deleteExampleData(DatabaseClient dbClient) { // [START spanner_postgresql_query_data] static void query(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() // Execute a single read or query against Cloud Spanner. - .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) { + dbClient + .singleUse() // Execute a single read or query against Cloud Spanner. + .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), @@ -287,12 +295,12 @@ static void query(DatabaseClient dbClient) { // [START spanner_postgresql_read_data] static void read(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() - .read( - "Albums", - KeySet.all(), // Read all rows in a table. - Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) { + dbClient + .singleUse() + .read( + "Albums", + KeySet.all(), // Read all rows in a table. + Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), @@ -303,15 +311,12 @@ static void read(DatabaseClient dbClient) { // [END spanner_postgresql_read_data] // [START spanner_postgresql_add_column] - static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseId dbId) { - OperationFuture op = adminClient.updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget bigint"), - null); + static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); + adminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget bigint")).get(); System.out.println("Added MarketingBudget column"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -404,11 +409,11 @@ static void queryMarketingBudget(DatabaseClient dbClient) { // null. A try-with-resource block is used to automatically release resources held by // ResultSet. try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery(Statement.of("SELECT singerid as \"SingerId\", " - + "albumid as \"AlbumId\", marketingbudget as \"MarketingBudget\" " - + "FROM Albums"))) { + dbClient + .singleUse() + .executeQuery(Statement.of("SELECT singerid as \"SingerId\", " + + "albumid as \"AlbumId\", marketingbudget as \"MarketingBudget\" " + + "FROM Albums"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", @@ -424,16 +429,12 @@ static void queryMarketingBudget(DatabaseClient dbClient) { // [END spanner_postgresql_query_data_with_new_column] // [START spanner_postgresql_create_index] - static void addIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { - OperationFuture op = - adminClient.updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"), - null); + static void addIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); + adminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)")).get(); System.out.println("Added AlbumsByAlbumTitle index"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -449,13 +450,13 @@ static void addIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { // [START spanner_postgresql_read_data_with_index] static void readUsingIndex(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() - .readUsingIndex( - "Albums", - "AlbumsByAlbumTitle", - KeySet.all(), - Arrays.asList("AlbumId", "AlbumTitle"))) { + dbClient + .singleUse() + .readUsingIndex( + "Albums", + "AlbumsByAlbumTitle", + KeySet.all(), + Arrays.asList("AlbumId", "AlbumTitle"))) { while (resultSet.next()) { System.out.printf("%d %s\n", resultSet.getLong(0), resultSet.getString(1)); } @@ -464,17 +465,14 @@ static void readUsingIndex(DatabaseClient dbClient) { // [END spanner_postgresql_read_data_with_index] // [START spanner_postgresql_create_storing_index] - static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { - OperationFuture op = adminClient.updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList( - "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " - + "INCLUDE (MarketingBudget)"), - null); + static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); + adminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList( + "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " + + "INCLUDE (MarketingBudget)")).get(); System.out.println("Added AlbumsByAlbumTitle2 index"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -493,13 +491,13 @@ static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { static void readStoringIndex(DatabaseClient dbClient) { // We can read MarketingBudget also from the index since it stores a copy of MarketingBudget. try (ResultSet resultSet = - dbClient - .singleUse() - .readUsingIndex( - "Albums", - "AlbumsByAlbumTitle2", - KeySet.all(), - Arrays.asList("AlbumId", "AlbumTitle", "MarketingBudget"))) { + dbClient + .singleUse() + .readUsingIndex( + "Albums", + "AlbumsByAlbumTitle2", + KeySet.all(), + Arrays.asList("AlbumId", "AlbumTitle", "MarketingBudget"))) { while (resultSet.next()) { System.out.printf( "%d %s %s\n", @@ -526,8 +524,8 @@ static void readOnlyTransaction(DatabaseClient dbClient) { queryResultSet.getString(2)); } try (ResultSet readResultSet = - transaction.read( - "Albums", KeySet.all(), Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) { + transaction.read( + "Albums", KeySet.all(), Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) { while (readResultSet.next()) { System.out.printf( "%d %d %s\n", @@ -542,10 +540,10 @@ static void readOnlyTransaction(DatabaseClient dbClient) { // [START spanner_postgresql_query_singers_table] static void querySingersTable(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery(Statement.of("SELECT singerid as \"SingerId\", " - + "firstname as \"FirstName\", lastname as \"LastName\" FROM Singers"))) { + dbClient + .singleUse() + .executeQuery(Statement.of("SELECT singerid as \"SingerId\", " + + "firstname as \"FirstName\", lastname as \"LastName\" FROM Singers"))) { while (resultSet.next()) { System.out.printf( "%s %s %s\n", @@ -656,35 +654,31 @@ static void writeWithTransactionUsingDml(DatabaseClient dbClient) { // [START spanner_postgresql_create_table_using_ddl] // [START spanner_postgresql_create_database] - static void createTableUsingDdl(DatabaseAdminClient dbAdminClient, DatabaseId id) { - OperationFuture op = - dbAdminClient.updateDatabaseDdl( - id.getInstanceId().getInstance(), - id.getDatabase(), - Arrays.asList( - "CREATE TABLE Singers (" - + " SingerId bigint NOT NULL," - + " FirstName character varying(1024)," - + " LastName character varying(1024)," - + " SingerInfo bytea," - + " FullName character varying(2048) GENERATED " - + " ALWAYS AS (FirstName || ' ' || LastName) STORED," - + " PRIMARY KEY (SingerId)" - + ")", - "CREATE TABLE Albums (" - + " SingerId bigint NOT NULL," - + " AlbumId bigint NOT NULL," - + " AlbumTitle character varying(1024)," - + " PRIMARY KEY (SingerId, AlbumId)" - + ") INTERLEAVE IN PARENT Singers ON DELETE CASCADE"), - null); + static void createTableUsingDdl(DatabaseAdminClient dbAdminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); - System.out.println("Created Singers & Albums tables in database: [" + id + "]"); + dbAdminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList( + "CREATE TABLE Singers (" + + " SingerId bigint NOT NULL," + + " FirstName character varying(1024)," + + " LastName character varying(1024)," + + " SingerInfo bytea," + + " FullName character varying(2048) GENERATED " + + " ALWAYS AS (FirstName || ' ' || LastName) STORED," + + " PRIMARY KEY (SingerId)" + + ")", + "CREATE TABLE Albums (" + + " SingerId bigint NOT NULL," + + " AlbumId bigint NOT NULL," + + " AlbumTitle character varying(1024)," + + " PRIMARY KEY (SingerId, AlbumId)" + + ") INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).get(); + System.out.println("Created Singers & Albums tables in database: [" + databaseName + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. - throw (SpannerException) e.getCause(); + throw SpannerExceptionFactory.asSpannerException(e); } catch (InterruptedException e) { // Throw when a thread is waiting, sleeping, or otherwise occupied, // and the thread is interrupted, either before or during the activity. @@ -697,11 +691,11 @@ static void createTableUsingDdl(DatabaseAdminClient dbAdminClient, DatabaseId id // [START spanner_postgresql_read_stale_data] static void readStaleData(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse(TimestampBound.ofExactStaleness(15, TimeUnit.SECONDS)) - .read( - "Albums", KeySet.all(), - Arrays.asList("SingerId", "AlbumId", "MarketingBudget"))) { + dbClient + .singleUse(TimestampBound.ofExactStaleness(15, TimeUnit.SECONDS)) + .read( + "Albums", KeySet.all(), + Arrays.asList("SingerId", "AlbumId", "MarketingBudget"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", @@ -749,17 +743,14 @@ static void updateWithTimestamp(DatabaseClient dbClient) { // [END spanner_postgresql_update_data_with_timestamp_column] // [START spanner_postgresql_add_timestamp_column] - static void addLastUpdateTimestampColumn(DatabaseAdminClient adminClient, DatabaseId dbId) { - OperationFuture op = - adminClient.updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList( - "ALTER TABLE Albums ADD COLUMN LastUpdateTime spanner.commit_timestamp"), - null); + static void addLastUpdateTimestampColumn( + DatabaseAdminClient adminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); + adminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList( + "ALTER TABLE Albums ADD COLUMN LastUpdateTime spanner.commit_timestamp")).get(); System.out.println("Added LastUpdateTime as a timestamp column in Albums table."); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -778,14 +769,14 @@ static void queryMarketingBudgetWithTimestamp(DatabaseClient dbClient) { // null. A try-with-resource block is used to automatically release resources held by // ResultSet. try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery( - Statement.of( - "SELECT singerid as \"SingerId\", albumid as \"AlbumId\", " - + "marketingbudget as \"MarketingBudget\"," - + "lastupdatetime as \"LastUpdateTime\" FROM Albums" - + " ORDER BY LastUpdateTime DESC"))) { + dbClient + .singleUse() + .executeQuery( + Statement.of( + "SELECT singerid as \"SingerId\", albumid as \"AlbumId\", " + + "marketingbudget as \"MarketingBudget\"," + + "lastupdatetime as \"LastUpdateTime\" FROM Albums" + + " ORDER BY LastUpdateTime DESC"))) { while (resultSet.next()) { System.out.printf( "%d %d %s %s\n", @@ -801,24 +792,20 @@ static void queryMarketingBudgetWithTimestamp(DatabaseClient dbClient) { // [END spanner_postgresql_query_data_with_timestamp_column] // [START spanner_postgresql_create_table_with_timestamp_column] - static void createTableWithTimestamp(DatabaseAdminClient dbAdminClient, DatabaseId id) { - OperationFuture op = - dbAdminClient.updateDatabaseDdl( - id.getInstanceId().getInstance(), - id.getDatabase(), - Arrays.asList( - "CREATE TABLE Performances (" - + " SingerId BIGINT NOT NULL," - + " VenueId BIGINT NOT NULL," - + " Revenue BIGINT," - + " LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL," - + " PRIMARY KEY (SingerId, VenueId))" - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE"), - null); + static void createTableWithTimestamp(DatabaseAdminClient dbAdminClient, + DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); - System.out.println("Created Performances table in database: [" + id + "]"); + dbAdminClient.updateDatabaseDdlAsync(databaseName, + Arrays.asList( + "CREATE TABLE Performances (" + + " SingerId BIGINT NOT NULL," + + " VenueId BIGINT NOT NULL," + + " Revenue BIGINT," + + " LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL," + + " PRIMARY KEY (SingerId, VenueId))" + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).get(); + System.out.println("Created Performances table in database: [" + databaseName + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -855,13 +842,13 @@ static void queryPerformancesTable(DatabaseClient dbClient) { // null. A try-with-resource block is used to automatically release resources held by // ResultSet. try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery( - Statement.of( - "SELECT singerid as \"SingerId\", venueid as \"VenueId\", " - + "revenue as \"Revenue\", lastupdatetime as \"LastUpdateTime\" " - + "FROM Performances ORDER BY LastUpdateTime DESC"))) { + dbClient + .singleUse() + .executeQuery( + Statement.of( + "SELECT singerid as \"SingerId\", venueid as \"VenueId\", " + + "revenue as \"Revenue\", lastupdatetime as \"LastUpdateTime\" " + + "FROM Performances ORDER BY LastUpdateTime DESC"))) { while (resultSet.next()) { System.out.printf( "%d %d %s %s\n", @@ -994,27 +981,24 @@ static void updateUsingBatchDml(DatabaseClient dbClient) { // [END spanner_postgresql_dml_batch_update] // [START spanner_postgresql_create_table_with_datatypes] - static void createTableWithDatatypes(DatabaseAdminClient dbAdminClient, DatabaseId id) { - OperationFuture op = - dbAdminClient.updateDatabaseDdl( - id.getInstanceId().getInstance(), - id.getDatabase(), - Arrays.asList( - "CREATE TABLE Venues (" - + " VenueId BIGINT NOT NULL," - + " VenueName character varying(100)," - + " VenueInfo bytea," - + " Capacity BIGINT," - + " OutdoorVenue BOOL, " - + " PopularityScore FLOAT8, " - + " Revenue NUMERIC, " - + " LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL," - + " PRIMARY KEY (VenueId))"), - null); + static void createTableWithDatatypes(DatabaseAdminClient dbAdminClient, + DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); - System.out.println("Created Venues table in database: [" + id + "]"); + dbAdminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList( + "CREATE TABLE Venues (" + + " VenueId BIGINT NOT NULL," + + " VenueName character varying(100)," + + " VenueInfo bytea," + + " Capacity BIGINT," + + " OutdoorVenue BOOL, " + + " PopularityScore FLOAT8, " + + " Revenue NUMERIC, " + + " LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL," + + " PRIMARY KEY (VenueId))")).get(); + System.out.println("Created Venues table in database: [" + databaseName + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -1222,9 +1206,9 @@ static void clientWithQueryOptions(DatabaseId db) { Spanner spanner = options.getService(); DatabaseClient dbClient = spanner.getDatabaseClient(db); try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) { + dbClient + .singleUse() + .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2)); @@ -1236,19 +1220,19 @@ static void clientWithQueryOptions(DatabaseId db) { // [START spanner_postgresql_query_with_query_options] static void queryWithQueryOptions(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery( - Statement - .newBuilder("SELECT SingerId, AlbumId, AlbumTitle FROM Albums") - .withQueryOptions(ExecuteSqlRequest.QueryOptions - .newBuilder() - .setOptimizerVersion("1") - // The list of available statistics packages can be found by querying - // the "INFORMATION_SCHEMA.spanner_postgresql_STATISTICS" table. - .setOptimizerStatisticsPackage("latest") - .build()) - .build())) { + dbClient + .singleUse() + .executeQuery( + Statement + .newBuilder("SELECT SingerId, AlbumId, AlbumTitle FROM Albums") + .withQueryOptions(ExecuteSqlRequest.QueryOptions + .newBuilder() + .setOptimizerVersion("1") + // The list of available statistics packages can be found by querying + // the "INFORMATION_SCHEMA.spanner_postgresql_STATISTICS" table. + .setOptimizerStatisticsPackage("latest") + .build()) + .build())) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2)); @@ -1258,22 +1242,26 @@ static void queryWithQueryOptions(DatabaseClient dbClient) { // [END spanner_postgresql_query_with_query_options] // [START spanner_postgresql_list_backup_operations] - static void listBackupOperations(InstanceAdminClient instanceAdminClient, DatabaseId databaseId) { - Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance()); - // Get create backup operations for the sample database. - Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert( - TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, - TimeUnit.HOURS), 0); + static void listBackupOperations( + DatabaseAdminClient databaseAdminClient, + String projectId, String instanceId, + String databaseId, String backupId) { + com.google.spanner.admin.database.v1.InstanceName instanceName = + com.google.spanner.admin.database.v1.InstanceName.of(projectId, instanceId); + // Get 'CreateBackup' operations for the sample database. String filter = String.format( - "(metadata.database:%s) AND " - + "(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.CreateBackupMetadata) AND " - + "(metadata.progress.start_time > \"%s\")", - databaseId.getName(), last24Hours); - Page operations = instance - .listBackupOperations(Options.filter(filter)); - for (com.google.longrunning.Operation op : operations.iterateAll()) { + "(metadata.@type:type.googleapis.com/" + + "google.spanner.admin.database.v1.CreateBackupMetadata) " + + "AND (metadata.database:%s)", + DatabaseName.of(projectId, instanceId, databaseId).toString()); + ListBackupOperationsRequest listBackupOperationsRequest = + ListBackupOperationsRequest.newBuilder() + .setParent(instanceName.toString()).setFilter(filter).build(); + ListBackupOperationsPagedResponse createBackupOperations + = databaseAdminClient.listBackupOperations(listBackupOperationsRequest); + System.out.println("Create Backup Operations:"); + for (Operation op : createBackupOperations.iterateAll()) { try { CreateBackupMetadata metadata = op.getMetadata().unpack(CreateBackupMetadata.class); System.out.println( @@ -1287,23 +1275,55 @@ static void listBackupOperations(InstanceAdminClient instanceAdminClient, Databa System.err.println(e.getMessage()); } } + // Get copy backup operations for the sample database. + filter = String.format( + "(metadata.@type:type.googleapis.com/" + + "google.spanner.admin.database.v1.CopyBackupMetadata) " + + "AND (metadata.source_backup:%s)", + BackupName.of(projectId, instanceId, backupId).toString()); + listBackupOperationsRequest = + ListBackupOperationsRequest.newBuilder() + .setParent(instanceName.toString()).setFilter(filter).build(); + ListBackupOperationsPagedResponse copyBackupOperations = + databaseAdminClient.listBackupOperations(listBackupOperationsRequest); + System.out.println("Copy Backup Operations:"); + for (Operation op : copyBackupOperations.iterateAll()) { + try { + CopyBackupMetadata copyBackupMetadata = + op.getMetadata().unpack(CopyBackupMetadata.class); + System.out.println( + String.format( + "Copy Backup %s on backup %s pending: %d%% complete", + copyBackupMetadata.getName(), + copyBackupMetadata.getSourceBackup(), + copyBackupMetadata.getProgress().getProgressPercent())); + } catch (InvalidProtocolBufferException e) { + // The returned operation does not contain CopyBackupMetadata. + System.err.println(e.getMessage()); + } + } } // [END spanner_postgresql_list_backup_operations] // [START spanner_postgresql_list_database_operations] static void listDatabaseOperations( - InstanceAdminClient instanceAdminClient, - DatabaseAdminClient dbAdminClient, - InstanceId instanceId) { - Instance instance = instanceAdminClient.getInstance(instanceId.getInstance()); + DatabaseAdminClient dbAdminClient, String projectId, String instanceId) { // Get optimize restored database operations. - Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert( - TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, - TimeUnit.HOURS), 0); + com.google.cloud.Timestamp last24Hours = com.google.cloud.Timestamp.ofTimeSecondsAndNanos( + TimeUnit.SECONDS.convert( + TimeUnit.HOURS.convert(com.google.cloud.Timestamp.now().getSeconds(), TimeUnit.SECONDS) + - 24, + TimeUnit.HOURS), 0); String filter = String.format("(metadata.@type:type.googleapis.com/" + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) AND " + "(metadata.progress.start_time > \"%s\")", last24Hours); - for (Operation op : instance.listDatabaseOperations(Options.filter(filter)).iterateAll()) { + ListDatabaseOperationsRequest listDatabaseOperationsRequest = + ListDatabaseOperationsRequest.newBuilder() + .setParent(com.google.spanner.admin.instance.v1.InstanceName.of( + projectId, instanceId).toString()).setFilter(filter).build(); + ListDatabaseOperationsPagedResponse pagedResponse + = dbAdminClient.listDatabaseOperations(listDatabaseOperationsRequest); + for (Operation op : pagedResponse.iterateAll()) { try { OptimizeRestoredDatabaseMetadata metadata = op.getMetadata().unpack(OptimizeRestoredDatabaseMetadata.class); @@ -1322,12 +1342,15 @@ static void listDatabaseOperations( static void run( DatabaseClient dbClient, DatabaseAdminClient dbAdminClient, - InstanceAdminClient instanceAdminClient, String command, - DatabaseId database) { + DatabaseId database, + String backupId) { + DatabaseName databaseName = DatabaseName.of(database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase()); switch (command) { - case "createdatabase": - createPostgreSqlDatabase(dbAdminClient, database); + case "createpgdatabase": + createPostgreSqlDatabase(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase()); break; case "write": writeExampleData(dbClient); @@ -1342,7 +1365,7 @@ static void run( read(dbClient); break; case "addmarketingbudget": - addMarketingBudget(dbAdminClient, database); + addMarketingBudget(dbAdminClient, databaseName); break; case "update": update(dbClient); @@ -1354,13 +1377,13 @@ static void run( queryMarketingBudget(dbClient); break; case "addindex": - addIndex(dbAdminClient, database); + addIndex(dbAdminClient, databaseName); break; case "readindex": readUsingIndex(dbClient); break; case "addstoringindex": - addStoringIndex(dbAdminClient, database); + addStoringIndex(dbAdminClient, databaseName); break; case "readstoringindex": readStoringIndex(dbClient); @@ -1381,13 +1404,13 @@ static void run( writeWithTransactionUsingDml(dbClient); break; case "createtableusingddl": - createTableUsingDdl(dbAdminClient, database); + createTableUsingDdl(dbAdminClient, databaseName); break; case "readstaledata": readStaleData(dbClient); break; case "addlastupdatetimestampcolumn": - addLastUpdateTimestampColumn(dbAdminClient, database); + addLastUpdateTimestampColumn(dbAdminClient, databaseName); break; case "updatewithtimestamp": updateWithTimestamp(dbClient); @@ -1396,7 +1419,7 @@ static void run( queryMarketingBudgetWithTimestamp(dbClient); break; case "createtablewithtimestamp": - createTableWithTimestamp(dbAdminClient, database); + createTableWithTimestamp(dbAdminClient, databaseName); break; case "writewithtimestamp": writeExampleDataWithTimestamp(dbClient); @@ -1426,7 +1449,7 @@ static void run( updateUsingBatchDml(dbClient); break; case "createtablewithdatatypes": - createTableWithDatatypes(dbAdminClient, database); + createTableWithDatatypes(dbAdminClient, databaseName); break; case "writedatatypesdata": writeDatatypesData(dbClient); @@ -1459,10 +1482,12 @@ static void run( queryWithQueryOptions(dbClient); break; case "listbackupoperations": - listBackupOperations(instanceAdminClient, database); + listBackupOperations(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase(), backupId); break; case "listdatabaseoperations": - listDatabaseOperations(instanceAdminClient, dbAdminClient, database.getInstanceId()); + listDatabaseOperations(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance()); break; default: printUsageAndExit(); @@ -1525,9 +1550,10 @@ public static void main(String[] args) { // [START spanner_init_client] SpannerOptions options = SpannerOptions.newBuilder().build(); Spanner spanner = options.getService(); + DatabaseAdminClient dbAdminClient = null; try { // [END spanner_init_client] - String command = args[0]; + final String command = args[0]; DatabaseId db = DatabaseId.of(options.getProjectId(), args[1], args[2]); // This will return the default project id based on the environment. @@ -1539,23 +1565,35 @@ public static void main(String[] args) { + clientProject); printUsageAndExit(); } + // Generate a backup id for the sample database. + String backupId = null; + if (args.length == 4) { + backupId = args[3]; + } + // [START spanner_init_client] DatabaseClient dbClient = spanner.getDatabaseClient(db); - DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + dbAdminClient = spanner.createDatabaseAdminClient(); // [END spanner_init_client] // Use client here... - run(dbClient, dbAdminClient, instanceAdminClient, command, db); + run(dbClient, dbAdminClient, command, db, backupId); // [START spanner_init_client] } finally { + if (dbAdminClient != null) { + if (!dbAdminClient.isShutdown() || !dbAdminClient.isTerminated()) { + dbAdminClient.close(); + } + } spanner.close(); } // [END spanner_init_client] System.out.println("Closed client"); } - /** Class to contain singer sample data. */ + /** + * Class to contain singer sample data. + */ static class Singer { final long singerId; @@ -1569,7 +1607,9 @@ static class Singer { } } - /** Class to contain album sample data. */ + /** + * Class to contain album sample data. + */ static class Album { final long singerId; diff --git a/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithEncryptionKey.java index fa87d98151..af101f96cc 100644 --- a/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithEncryptionKey.java +++ b/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithEncryptionKey.java @@ -18,17 +18,17 @@ // [START spanner_restore_backup_with_encryption_key] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.BackupId; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Restore; +import static com.google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.encryption.EncryptionConfigs; -import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.spanner.admin.database.v1.BackupName; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.InstanceName; +import com.google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig; +import com.google.spanner.admin.database.v1.RestoreDatabaseRequest; import java.util.concurrent.ExecutionException; public class RestoreBackupWithEncryptionKey { @@ -43,8 +43,8 @@ static void restoreBackupWithEncryptionKey() { "projects/" + projectId + "/locations//keyRings//cryptoKeys/"; try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { restoreBackupWithEncryptionKey( adminClient, projectId, @@ -57,19 +57,18 @@ static void restoreBackupWithEncryptionKey() { static Void restoreBackupWithEncryptionKey(DatabaseAdminClient adminClient, String projectId, String instanceId, String backupId, String restoreId, String kmsKeyName) { - final Restore restore = adminClient - .newRestoreBuilder( - BackupId.of(projectId, instanceId, backupId), - DatabaseId.of(projectId, instanceId, restoreId)) - .setEncryptionConfig(EncryptionConfigs.customerManagedEncryption(kmsKeyName)) - .build(); - final OperationFuture operation = adminClient - .restoreDatabase(restore); - + RestoreDatabaseRequest request = + RestoreDatabaseRequest.newBuilder() + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setDatabaseId(restoreId) + .setBackup(BackupName.of(projectId, instanceId, backupId).toString()) + .setEncryptionConfig(RestoreDatabaseEncryptionConfig.newBuilder() + .setEncryptionType(CUSTOMER_MANAGED_ENCRYPTION).setKmsKeyName(kmsKeyName)).build(); Database database; try { System.out.println("Waiting for operation to complete..."); - database = operation.get(); + database = adminClient.restoreDatabaseAsync(request).get(); + ; } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw SpannerExceptionFactory.asSpannerException(e.getCause()); @@ -81,9 +80,9 @@ static Void restoreBackupWithEncryptionKey(DatabaseAdminClient adminClient, System.out.printf( "Database %s restored to %s from backup %s using encryption key %s%n", - database.getRestoreInfo().getSourceDatabase(), - database.getId(), - database.getRestoreInfo().getBackup(), + database.getRestoreInfo().getBackupInfo().getSourceDatabase(), + database.getName(), + database.getRestoreInfo().getBackupInfo().getBackup(), database.getEncryptionConfig().getKmsKeyName() ); return null; diff --git a/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java b/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java index 43c04aaa8d..d406225c28 100644 --- a/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java @@ -20,28 +20,19 @@ import com.google.api.gax.longrunning.OperationFuture; import com.google.api.gax.longrunning.OperationSnapshot; -import com.google.api.gax.paging.Page; import com.google.api.gax.retrying.RetryingFuture; +import com.google.api.gax.rpc.NotFoundException; import com.google.api.gax.rpc.StatusCode; +import com.google.api.gax.rpc.StatusCode.Code; import com.google.cloud.ByteArray; import com.google.cloud.Date; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Backup; -import com.google.cloud.spanner.BackupId; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Instance; -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceId; import com.google.cloud.spanner.Key; import com.google.cloud.spanner.KeyRange; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options; import com.google.cloud.spanner.ReadOnlyTransaction; -import com.google.cloud.spanner.RestoreInfo; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerBatchUpdateException; @@ -53,27 +44,41 @@ import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListBackupOperationsPagedResponse; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListBackupsPagedResponse; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabaseOperationsPagedResponse; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; import com.google.common.io.BaseEncoding; import com.google.longrunning.Operation; +import com.google.protobuf.FieldMask; import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Timestamp; +import com.google.spanner.admin.database.v1.Backup; +import com.google.spanner.admin.database.v1.BackupInfo; +import com.google.spanner.admin.database.v1.BackupName; import com.google.spanner.admin.database.v1.CopyBackupMetadata; import com.google.spanner.admin.database.v1.CreateBackupMetadata; -import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.InstanceName; +import com.google.spanner.admin.database.v1.ListBackupOperationsRequest; +import com.google.spanner.admin.database.v1.ListBackupsRequest; +import com.google.spanner.admin.database.v1.ListDatabaseOperationsRequest; import com.google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata; import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.admin.database.v1.RestoreDatabaseRequest; +import com.google.spanner.admin.database.v1.RestoreInfo; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.math.BigDecimal; import java.time.Instant; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import org.threeten.bp.LocalDate; -import org.threeten.bp.LocalDateTime; -import org.threeten.bp.OffsetDateTime; -import org.threeten.bp.temporal.ChronoField; /** * Example code for using the Cloud Spanner API. This example demonstrates all the common operations @@ -93,7 +98,9 @@ */ public class SpannerSample { - /** Class to contain singer sample data. */ + /** + * Class to contain singer sample data. + */ static class Singer { final long singerId; @@ -107,7 +114,9 @@ static class Singer { } } - /** Class to contain album sample data. */ + /** + * Class to contain album sample data. + */ static class Album { final long singerId; @@ -121,7 +130,9 @@ static class Album { } } - /** Class to contain performance sample data. */ + /** + * Class to contain performance sample data. + */ static class Performance { final long singerId; @@ -137,7 +148,9 @@ static class Performance { } } - /** Class to contain venue sample data. */ + /** + * Class to contain venue sample data. + */ static class Venue { final long venueId; @@ -175,17 +188,6 @@ static class Venue { } } - /** Get a database id to restore a backup to from the sample database id. */ - static String createRestoredSampleDbId(DatabaseId database) { - int index = database.getDatabase().indexOf('-'); - String prefix = database.getDatabase().substring(0, index); - String restoredDbId = database.getDatabase().replace(prefix, "restored"); - if (restoredDbId.length() > 30) { - restoredDbId = restoredDbId.substring(0, 30); - } - return restoredDbId; - } - // [START spanner_insert_data] static final List SINGERS = Arrays.asList( @@ -272,12 +274,13 @@ static String createRestoredSampleDbId(DatabaseId database) { // [END spanner_insert_datatypes_data] // [START spanner_create_database] - static void createDatabase(DatabaseAdminClient dbAdminClient, DatabaseId id) { - OperationFuture op = - dbAdminClient.createDatabase( - id.getInstanceId().getInstance(), - id.getDatabase(), - Arrays.asList( + static void createDatabase(DatabaseAdminClient dbAdminClient, + InstanceName instanceName, String databaseId) { + CreateDatabaseRequest createDatabaseRequest = + CreateDatabaseRequest.newBuilder() + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .setParent(instanceName.toString()) + .addAllExtraStatements(Arrays.asList( "CREATE TABLE Singers (" + " SingerId INT64 NOT NULL," + " FirstName STRING(1024)," @@ -291,11 +294,12 @@ static void createDatabase(DatabaseAdminClient dbAdminClient, DatabaseId id) { + " AlbumId INT64 NOT NULL," + " AlbumTitle STRING(MAX)" + ") PRIMARY KEY (SingerId, AlbumId)," - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")); + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).build(); try { // Initiate the request which returns an OperationFuture. - Database db = op.get(); - System.out.println("Created database [" + db.getId() + "]"); + com.google.spanner.admin.database.v1.Database db = + dbAdminClient.createDatabaseAsync(createDatabaseRequest).get(); + System.out.println("Created database [" + db.getName() + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -308,25 +312,23 @@ static void createDatabase(DatabaseAdminClient dbAdminClient, DatabaseId id) { // [END spanner_create_database] // [START spanner_create_table_with_timestamp_column] - static void createTableWithTimestamp(DatabaseAdminClient dbAdminClient, DatabaseId id) { - OperationFuture op = - dbAdminClient.updateDatabaseDdl( - id.getInstanceId().getInstance(), - id.getDatabase(), - Arrays.asList( - "CREATE TABLE Performances (" - + " SingerId INT64 NOT NULL," - + " VenueId INT64 NOT NULL," - + " EventDate Date," - + " Revenue INT64, " - + " LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)" - + ") PRIMARY KEY (SingerId, VenueId, EventDate)," - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE"), - null); + static void createTableWithTimestamp(DatabaseAdminClient dbAdminClient, + DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); - System.out.println("Created Performances table in database: [" + id + "]"); + dbAdminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList( + "CREATE TABLE Performances (" + + " SingerId INT64 NOT NULL," + + " VenueId INT64 NOT NULL," + + " EventDate Date," + + " Revenue INT64, " + + " LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)" + + ") PRIMARY KEY (SingerId, VenueId, EventDate)," + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).get(); + System.out.println( + "Created Performances table in database: [" + databaseName.toString() + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -446,16 +448,12 @@ static void read(DatabaseClient dbClient) { // [END spanner_read_data] // [START spanner_add_column] - static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseId dbId) { - OperationFuture op = - adminClient.updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"), - null); + static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); + adminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64")).get(); System.out.println("Added MarketingBudget column"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -565,16 +563,12 @@ static void queryMarketingBudget(DatabaseClient dbClient) { // [END spanner_query_data_with_new_column] // [START spanner_create_index] - static void addIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { - OperationFuture op = - adminClient.updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"), - null); + static void addIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); + adminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)")).get(); System.out.println("Added AlbumsByAlbumTitle index"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -636,18 +630,14 @@ static void readUsingIndex(DatabaseClient dbClient) { // [END spanner_read_data_with_index] // [START spanner_create_storing_index] - static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { - OperationFuture op = - adminClient.updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList( - "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " - + "STORING (MarketingBudget)"), - null); + static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); + adminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList( + "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " + + "STORING (MarketingBudget)")).get(); System.out.println("Added AlbumsByAlbumTitle2 index"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -729,18 +719,14 @@ static void readStaleData(DatabaseClient dbClient) { // [END spanner_read_stale_data] // [START spanner_add_timestamp_column] - static void addCommitTimestamp(DatabaseAdminClient adminClient, DatabaseId dbId) { - OperationFuture op = - adminClient.updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList( - "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " - + "OPTIONS (allow_commit_timestamp=true)"), - null); + static void addCommitTimestamp(DatabaseAdminClient adminClient, DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); + adminClient.updateDatabaseDdlAsync( + databaseName, + Arrays.asList( + "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " + + "OPTIONS (allow_commit_timestamp=true)")).get(); System.out.println("Added LastUpdateTime as a commit timestamp column in Albums table."); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -1186,18 +1172,18 @@ static void writeWithTransactionUsingDml(DatabaseClient dbClient) { album2Budget -= transfer; Statement updateStatement = Statement.newBuilder( - "UPDATE Albums " - + "SET MarketingBudget = @AlbumBudget " - + "WHERE SingerId = 1 and AlbumId = 1") + "UPDATE Albums " + + "SET MarketingBudget = @AlbumBudget " + + "WHERE SingerId = 1 and AlbumId = 1") .bind("AlbumBudget") .to(album1Budget) .build(); transaction.executeUpdate(updateStatement); Statement updateStatement2 = Statement.newBuilder( - "UPDATE Albums " - + "SET MarketingBudget = @AlbumBudget " - + "WHERE SingerId = 2 and AlbumId = 2") + "UPDATE Albums " + + "SET MarketingBudget = @AlbumBudget " + + "WHERE SingerId = 2 and AlbumId = 2") .bind("AlbumBudget") .to(album2Budget) .build(); @@ -1255,30 +1241,26 @@ static void updateUsingBatchDml(DatabaseClient dbClient) { // [END spanner_dml_batch_update] // [START spanner_create_table_with_datatypes] - static void createTableWithDatatypes(DatabaseAdminClient dbAdminClient, DatabaseId id) { - OperationFuture op = - dbAdminClient.updateDatabaseDdl( - id.getInstanceId().getInstance(), - id.getDatabase(), - Arrays.asList( - "CREATE TABLE Venues (" - + " VenueId INT64 NOT NULL," - + " VenueName STRING(100)," - + " VenueInfo BYTES(MAX)," - + " Capacity INT64," - + " AvailableDates ARRAY," - + " LastContactDate DATE," - + " OutdoorVenue BOOL, " - + " PopularityScore FLOAT64, " - + " Revenue NUMERIC, " - + " VenueDetails JSON, " - + " LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)" - + ") PRIMARY KEY (VenueId)"), - null); + static void createTableWithDatatypes(DatabaseAdminClient dbAdminClient, + DatabaseName databaseName) { try { // Initiate the request which returns an OperationFuture. - op.get(); - System.out.println("Created Venues table in database: [" + id + "]"); + dbAdminClient.updateDatabaseDdlAsync(databaseName, + Arrays.asList( + "CREATE TABLE Venues (" + + " VenueId INT64 NOT NULL," + + " VenueName STRING(100)," + + " VenueInfo BYTES(MAX)," + + " Capacity INT64," + + " AvailableDates ARRAY," + + " LastContactDate DATE," + + " OutdoorVenue BOOL, " + + " PopularityScore FLOAT64, " + + " Revenue NUMERIC, " + + " VenueDetails JSON, " + + " LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)" + + ") PRIMARY KEY (VenueId)")).get(); + System.out.println("Created Venues table in database: [" + databaseName.toString() + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -1570,74 +1552,76 @@ static void queryWithQueryOptions(DatabaseClient dbClient) { // [END spanner_query_with_query_options] // [START spanner_create_backup] - static void createBackup(DatabaseAdminClient dbAdminClient, DatabaseId databaseId, - BackupId backupId, Timestamp versionTime) { + static void createBackup(DatabaseAdminClient dbAdminClient, String projectId, String instanceId, + String databaseId, String backupId, Timestamp versionTime) { // Set expire time to 14 days from now. - Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS)); - Backup backup = - dbAdminClient - .newBackupBuilder(backupId) - .setDatabase(databaseId) - .setExpireTime(expireTime) - .setVersionTime(versionTime) - .build(); + Timestamp expireTime = + Timestamp.newBuilder().setSeconds(TimeUnit.MILLISECONDS.toSeconds(( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14)))).build(); + BackupName backupName = BackupName.of(projectId, instanceId, backupId); + Backup backup = Backup.newBuilder() + .setName(backupName.toString()) + .setDatabase(DatabaseName.of(projectId, instanceId, databaseId).toString()) + .setExpireTime(expireTime).setVersionTime(versionTime).build(); + // Initiate the request which returns an OperationFuture. - System.out.println("Creating backup [" + backup.getId() + "]..."); - OperationFuture op = backup.create(); + System.out.println("Creating backup [" + backupId + "]..."); try { // Wait for the backup operation to complete. - backup = op.get(); - System.out.println("Created backup [" + backup.getId() + "]"); + backup = dbAdminClient.createBackupAsync( + InstanceName.of(projectId, instanceId), backup, backupId).get(); + System.out.println("Created backup [" + backup.getName() + "]"); } catch (ExecutionException e) { - throw (SpannerException) e.getCause(); + throw SpannerExceptionFactory.asSpannerException(e); } catch (InterruptedException e) { throw SpannerExceptionFactory.propagateInterrupt(e); } // Reload the metadata of the backup from the server. - backup = backup.reload(); + backup = dbAdminClient.getBackup(backup.getName()); System.out.println( String.format( "Backup %s of size %d bytes was created at %s for version of database at %s", - backup.getId().getName(), - backup.getSize(), - LocalDateTime.ofEpochSecond( - backup.getProto().getCreateTime().getSeconds(), - backup.getProto().getCreateTime().getNanos(), - OffsetDateTime.now().getOffset()), - LocalDateTime.ofEpochSecond( - backup.getProto().getVersionTime().getSeconds(), - backup.getProto().getVersionTime().getNanos(), - OffsetDateTime.now().getOffset()) - )); + backup.getName(), + backup.getSizeBytes(), + java.time.OffsetDateTime.ofInstant( + Instant.ofEpochSecond(backup.getCreateTime().getSeconds(), + backup.getCreateTime().getNanos()), ZoneId.systemDefault()), + java.time.OffsetDateTime.ofInstant( + Instant.ofEpochSecond(backup.getVersionTime().getSeconds(), + backup.getVersionTime().getNanos()), ZoneId.systemDefault())) + ); } // [END spanner_create_backup] // [START spanner_cancel_backup_create] static void cancelCreateBackup( - DatabaseAdminClient dbAdminClient, DatabaseId databaseId, BackupId backupId) { + DatabaseAdminClient dbAdminClient, String projectId, String instanceId, + String databaseId, String backupId) { // Set expire time to 14 days from now. - Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS)); - - // Create a backup instance. - Backup backup = - dbAdminClient - .newBackupBuilder(backupId) - .setDatabase(databaseId) - .setExpireTime(expireTime) - .build(); - // Start the creation of a backup. - System.out.println("Creating backup [" + backup.getId() + "]..."); - OperationFuture op = backup.create(); + Timestamp expireTime = + Timestamp.newBuilder().setSeconds(TimeUnit.MILLISECONDS.toSeconds(( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14)))).build(); + BackupName backupName = BackupName.of(projectId, instanceId, backupId); + Backup backup = Backup.newBuilder() + .setName(backupName.toString()) + .setDatabase(DatabaseName.of(projectId, instanceId, databaseId).toString()) + .setExpireTime(expireTime).build(); + try { + // Start the creation of a backup. + System.out.println("Creating backup [" + backupId + "]..."); + OperationFuture op = dbAdminClient.createBackupAsync( + InstanceName.of(projectId, instanceId), backup, backupId); + // Try to cancel the backup operation. - System.out.println("Cancelling create backup operation for [" + backup.getId() + "]..."); - dbAdminClient.cancelOperation(op.getName()); + System.out.println("Cancelling create backup operation for [" + backupId + "]..."); + dbAdminClient.getOperationsClient().cancelOperation(op.getName()); + // Get a polling future for the running operation. This future will regularly poll the server // for the current status of the backup operation. RetryingFuture pollingFuture = op.getPollingFuture(); + // Wait for the operation to finish. // isDone will return true when the operation is complete, regardless of whether it was // successful or not. @@ -1647,11 +1631,11 @@ static void cancelCreateBackup( } if (pollingFuture.get().getErrorCode() == null) { // Backup was created before it could be cancelled. Delete the backup. - backup.delete(); - System.out.println("Backup operation for [" + backup.getId() + dbAdminClient.deleteBackup(backupName); + System.out.println("Backup operation for [" + backupId + "] successfully finished before it could be cancelled"); } else if (pollingFuture.get().getErrorCode().getCode() == StatusCode.Code.CANCELLED) { - System.out.println("Backup operation for [" + backup.getId() + "] successfully cancelled"); + System.out.println("Backup operation for [" + backupId + "] successfully cancelled"); } } catch (ExecutionException e) { throw SpannerExceptionFactory.newSpannerException(e.getCause()); @@ -1663,20 +1647,22 @@ static void cancelCreateBackup( // [START spanner_list_backup_operations] static void listBackupOperations( - InstanceAdminClient instanceAdminClient, DatabaseId databaseId, BackupId backupId) { - Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance()); - // Get create backup operations for the sample database. - Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert( - TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, - TimeUnit.HOURS), 0); + DatabaseAdminClient databaseAdminClient, + String projectId, String instanceId, + String databaseId, String backupId) { + InstanceName instanceName = InstanceName.of(projectId, instanceId); + // Get 'CreateBackup' operations for the sample database. String filter = String.format( - "(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.CreateBackupMetadata) " - + "AND (metadata.database:%s)", - databaseId.getName()); - Page createBackupOperations = instance.listBackupOperations( - Options.filter(filter)); + "(metadata.@type:type.googleapis.com/" + + "google.spanner.admin.database.v1.CreateBackupMetadata) " + + "AND (metadata.database:%s)", + DatabaseName.of(projectId, instanceId, databaseId).toString()); + ListBackupOperationsRequest listBackupOperationsRequest = + ListBackupOperationsRequest.newBuilder() + .setParent(instanceName.toString()).setFilter(filter).build(); + ListBackupOperationsPagedResponse createBackupOperations + = databaseAdminClient.listBackupOperations(listBackupOperationsRequest); System.out.println("Create Backup Operations:"); for (Operation op : createBackupOperations.iterateAll()) { try { @@ -1693,24 +1679,27 @@ static void listBackupOperations( } } // Get copy backup operations for the sample database. - filter = - String.format( - "(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.CopyBackupMetadata) " - + "AND (metadata.source_backup:%s)", - backupId.getName()); - Page copyBackupOperations = instance.listBackupOperations(Options.filter(filter)); + filter = String.format( + "(metadata.@type:type.googleapis.com/" + + "google.spanner.admin.database.v1.CopyBackupMetadata) " + + "AND (metadata.source_backup:%s)", + BackupName.of(projectId, instanceId, backupId).toString()); + listBackupOperationsRequest = + ListBackupOperationsRequest.newBuilder() + .setParent(instanceName.toString()).setFilter(filter).build(); + ListBackupOperationsPagedResponse copyBackupOperations = + databaseAdminClient.listBackupOperations(listBackupOperationsRequest); System.out.println("Copy Backup Operations:"); for (Operation op : copyBackupOperations.iterateAll()) { try { CopyBackupMetadata copyBackupMetadata = - op.getMetadata().unpack(CopyBackupMetadata.class); + op.getMetadata().unpack(CopyBackupMetadata.class); System.out.println( - String.format( - "Copy Backup %s on backup %s pending: %d%% complete", - copyBackupMetadata.getName(), - copyBackupMetadata.getSourceBackup(), - copyBackupMetadata.getProgress().getProgressPercent())); + String.format( + "Copy Backup %s on backup %s pending: %d%% complete", + copyBackupMetadata.getName(), + copyBackupMetadata.getSourceBackup(), + copyBackupMetadata.getProgress().getProgressPercent())); } catch (InvalidProtocolBufferException e) { // The returned operation does not contain CopyBackupMetadata. System.err.println(e.getMessage()); @@ -1721,18 +1710,23 @@ static void listBackupOperations( // [START spanner_list_database_operations] static void listDatabaseOperations( - InstanceAdminClient instanceAdminClient, - DatabaseAdminClient dbAdminClient, - InstanceId instanceId) { - Instance instance = instanceAdminClient.getInstance(instanceId.getInstance()); + DatabaseAdminClient dbAdminClient, String projectId, String instanceId) { // Get optimize restored database operations. - Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert( - TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, - TimeUnit.HOURS), 0); + com.google.cloud.Timestamp last24Hours = com.google.cloud.Timestamp.ofTimeSecondsAndNanos( + TimeUnit.SECONDS.convert( + TimeUnit.HOURS.convert(com.google.cloud.Timestamp.now().getSeconds(), TimeUnit.SECONDS) + - 24, + TimeUnit.HOURS), 0); String filter = String.format("(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) AND " - + "(metadata.progress.start_time > \"%s\")", last24Hours); - for (Operation op : instance.listDatabaseOperations(Options.filter(filter)).iterateAll()) { + + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) AND " + + "(metadata.progress.start_time > \"%s\")", last24Hours); + ListDatabaseOperationsRequest listDatabaseOperationsRequest = + ListDatabaseOperationsRequest.newBuilder() + .setParent(com.google.spanner.admin.instance.v1.InstanceName.of( + projectId, instanceId).toString()).setFilter(filter).build(); + ListDatabaseOperationsPagedResponse pagedResponse + = dbAdminClient.listDatabaseOperations(listDatabaseOperationsRequest); + for (Operation op : pagedResponse.iterateAll()) { try { OptimizeRestoredDatabaseMetadata metadata = op.getMetadata().unpack(OptimizeRestoredDatabaseMetadata.class); @@ -1750,74 +1744,92 @@ static void listDatabaseOperations( // [START spanner_list_backups] static void listBackups( - InstanceAdminClient instanceAdminClient, DatabaseId databaseId, BackupId backupId) { - Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance()); + DatabaseAdminClient dbAdminClient, String projectId, + String instanceId, String databaseId, String backupId) { + InstanceName instanceName = InstanceName.of(projectId, instanceId); // List all backups. System.out.println("All backups:"); - for (Backup backup : instance.listBackups().iterateAll()) { + for (Backup backup : dbAdminClient.listBackups( + instanceName.toString()).iterateAll()) { System.out.println(backup); } // List all backups with a specific name. System.out.println( - String.format("All backups with backup name containing \"%s\":", backupId.getBackup())); - for (Backup backup : instance.listBackups( - Options.filter(String.format("name:%s", backupId.getBackup()))).iterateAll()) { + String.format("All backups with backup name containing \"%s\":", backupId)); + ListBackupsRequest listBackupsRequest = + ListBackupsRequest.newBuilder().setParent(instanceName.toString()) + .setFilter(String.format("name:%s", backupId)).build(); + for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { System.out.println(backup); } // List all backups for databases whose name contains a certain text. System.out.println( String.format( - "All backups for databases with a name containing \"%s\":", - databaseId.getDatabase())); - for (Backup backup : instance.listBackups( - Options.filter(String.format("database:%s", databaseId.getDatabase()))).iterateAll()) { + "All backups for databases with a name containing \"%s\":", databaseId)); + listBackupsRequest = + ListBackupsRequest.newBuilder().setParent(instanceName.toString()) + .setFilter(String.format("database:%s", databaseId)).build(); + for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { System.out.println(backup); } // List all backups that expire before a certain time. - Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30), TimeUnit.MILLISECONDS)); - System.out.println(String.format("All backups that expire before %s:", expireTime.toString())); - for (Backup backup : - instance.listBackups( - Options.filter(String.format("expire_time < \"%s\"", expireTime.toString()))) - .iterateAll()) { + com.google.cloud.Timestamp expireTime = com.google.cloud.Timestamp.ofTimeMicroseconds( + TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30), TimeUnit.MILLISECONDS)); + + System.out.println(String.format("All backups that expire before %s:", expireTime)); + listBackupsRequest = + ListBackupsRequest.newBuilder().setParent(instanceName.toString()) + .setFilter(String.format("expire_time < \"%s\"", expireTime)).build(); + + for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { System.out.println(backup); } // List all backups with size greater than a certain number of bytes. + listBackupsRequest = + ListBackupsRequest.newBuilder().setParent(instanceName.toString()) + .setFilter("size_bytes > 100").build(); + System.out.println("All backups with size greater than 100 bytes:"); - for (Backup backup : instance.listBackups(Options.filter("size_bytes > 100")).iterateAll()) { + for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { System.out.println(backup); } // List all backups with a create time after a certain timestamp and that are also ready. - Timestamp createTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1), TimeUnit.MILLISECONDS)); + com.google.cloud.Timestamp createTime = com.google.cloud.Timestamp.ofTimeMicroseconds( + TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1), TimeUnit.MILLISECONDS)); + System.out.println( String.format( "All databases created after %s and that are ready:", createTime.toString())); - for (Backup backup : - instance - .listBackups(Options.filter( - String.format("create_time >= \"%s\" AND state:READY", createTime.toString()))) - .iterateAll()) { + listBackupsRequest = + ListBackupsRequest.newBuilder().setParent(instanceName.toString()) + .setFilter(String.format( + "create_time >= \"%s\" AND state:READY", createTime.toString())).build(); + for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { System.out.println(backup); } // List backups using pagination. System.out.println("All backups, listed using pagination:"); - Page page = instance.listBackups(Options.pageSize(10)); + listBackupsRequest = + ListBackupsRequest.newBuilder().setParent(instanceName.toString()).setPageSize(10).build(); while (true) { - for (Backup backup : page.getValues()) { + ListBackupsPagedResponse response = dbAdminClient.listBackups(listBackupsRequest); + for (Backup backup : response.getPage().iterateAll()) { System.out.println(backup); } - if (!page.hasNextPage()) { + String nextPageToken = response.getNextPageToken(); + if (!Strings.isNullOrEmpty(nextPageToken)) { + listBackupsRequest = listBackupsRequest.toBuilder().setPageToken(nextPageToken).build(); + } else { break; } - page = page.getNextPage(); } } // [END spanner_list_backups] @@ -1825,31 +1837,35 @@ static void listBackups( // [START spanner_restore_backup] static void restoreBackup( DatabaseAdminClient dbAdminClient, - BackupId backupId, - DatabaseId sourceDatabaseId, - DatabaseId restoreToDatabase) { - Backup backup = dbAdminClient.newBackupBuilder(backupId).build(); + String projectId, + String instanceId, + String backupId, + String restoreToDatabaseId) { + BackupName backupName = BackupName.of(projectId, instanceId, backupId); + Backup backup = dbAdminClient.getBackup(backupName); // Initiate the request which returns an OperationFuture. System.out.println(String.format( - "Restoring backup [%s] to database [%s]...", - backup.getId().toString(), - restoreToDatabase.toString())); + "Restoring backup [%s] to database [%s]...", backup.getName(), restoreToDatabaseId)); try { - OperationFuture op = backup.restore(restoreToDatabase); + RestoreDatabaseRequest request = + RestoreDatabaseRequest.newBuilder() + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setDatabaseId(restoreToDatabaseId) + .setBackup(backupName.toString()).build(); + OperationFuture op = + dbAdminClient.restoreDatabaseAsync(request); // Wait until the database has been restored. - Database db = op.get(); - // Refresh database metadata and get the restore info. - RestoreInfo restore = db.reload().getRestoreInfo(); - Timestamp versionTime = Timestamp.fromProto(restore - .getProto() - .getBackupInfo() - .getVersionTime()); + com.google.spanner.admin.database.v1.Database db = op.get(); + // Get the restore info. + RestoreInfo restoreInfo = db.getRestoreInfo(); + BackupInfo backupInfo = restoreInfo.getBackupInfo(); + System.out.println( "Restored database [" - + restore.getSourceDatabase().getName() + + db.getName() + "] from [" - + restore.getBackup().getName() - + "] with version time [" + versionTime + "]"); + + restoreInfo.getBackupInfo().getBackup() + + "] with version time [" + backupInfo.getVersionTime() + "]"); } catch (ExecutionException e) { throw SpannerExceptionFactory.newSpannerException(e.getCause()); } catch (InterruptedException e) { @@ -1859,49 +1875,59 @@ static void restoreBackup( // [END spanner_restore_backup] // [START spanner_update_backup] - static void updateBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) { + static void updateBackup(DatabaseAdminClient dbAdminClient, String projectId, + String instanceId, String backupId) { + BackupName backupName = BackupName.of(projectId, instanceId, backupId); + // Get current backup metadata. - Backup backup = dbAdminClient.newBackupBuilder(backupId).build().reload(); + Backup backup = dbAdminClient.getBackup(backupName); // Add 30 days to the expire time. // Expire time must be within 366 days of the create time of the backup. - Timestamp expireTime = - Timestamp.ofTimeMicroseconds( - TimeUnit.SECONDS.toMicros(backup.getExpireTime().getSeconds()) - + TimeUnit.NANOSECONDS.toMicros(backup.getExpireTime().getNanos()) + Timestamp currentExpireTime = backup.getExpireTime(); + com.google.cloud.Timestamp newExpireTime = + com.google.cloud.Timestamp.ofTimeMicroseconds( + TimeUnit.SECONDS.toMicros(currentExpireTime.getSeconds()) + + TimeUnit.NANOSECONDS.toMicros(currentExpireTime.getNanos()) + TimeUnit.DAYS.toMicros(30L)); + // New Expire Time must be less than Max Expire Time - expireTime = expireTime.compareTo(backup.getMaxExpireTime()) - < 0 ? expireTime : backup.getMaxExpireTime(); - int timeDiff = expireTime.compareTo(backup.getExpireTime()); - Timestamp newExpireTime = (timeDiff < 0) ? expireTime : backup.getExpireTime(); + newExpireTime = + newExpireTime.compareTo(com.google.cloud.Timestamp.fromProto(backup.getMaxExpireTime())) + < 0 ? newExpireTime : com.google.cloud.Timestamp.fromProto(backup.getMaxExpireTime()); System.out.println(String.format( "Updating expire time of backup [%s] to %s...", backupId.toString(), - LocalDateTime.ofEpochSecond( - expireTime.getSeconds(), - expireTime.getNanos(), - OffsetDateTime.now().getOffset()).toString())); + java.time.OffsetDateTime.ofInstant( + Instant.ofEpochSecond(newExpireTime.getSeconds(), + newExpireTime.getNanos()), ZoneId.systemDefault()))); // Update expire time. - backup = backup.toBuilder().setExpireTime(expireTime).build(); - backup.updateExpireTime(); + backup = backup.toBuilder().setExpireTime(newExpireTime.toProto()).build(); + dbAdminClient.updateBackup(backup, + FieldMask.newBuilder().addAllPaths(Lists.newArrayList("expire_time")).build()); System.out.println("Updated backup [" + backupId + "]"); } // [END spanner_update_backup] // [START spanner_delete_backup] - static void deleteBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) { - Backup backup = dbAdminClient.newBackupBuilder(backupId).build(); + static void deleteBackup(DatabaseAdminClient dbAdminClient, + String project, String instance, String backupId) { + BackupName backupName = BackupName.of(project, instance, backupId); + // Delete the backup. System.out.println("Deleting backup [" + backupId + "]..."); - backup.delete(); + dbAdminClient.deleteBackup(backupName); // Verify that the backup is deleted. - if (backup.exists()) { - System.out.println("Delete backup [" + backupId + "] failed"); - throw new RuntimeException("Delete backup [" + backupId + "] failed"); - } else { - System.out.println("Deleted backup [" + backupId + "]"); + try { + dbAdminClient.getBackup(backupName); + } catch (NotFoundException e) { + if (e.getStatusCode().getCode() == Code.NOT_FOUND) { + System.out.println("Deleted backup [" + backupId + "]"); + } else { + System.out.println("Delete backup [" + backupId + "] failed"); + throw new RuntimeException("Delete backup [" + backupId + "] failed", e); + } } } // [END spanner_delete_backup] @@ -1909,13 +1935,13 @@ static void deleteBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) { static void run( DatabaseClient dbClient, DatabaseAdminClient dbAdminClient, - InstanceAdminClient instanceAdminClient, String command, DatabaseId database, - BackupId backup) { + String backupId) { switch (command) { case "createdatabase": - createDatabase(dbAdminClient, database); + createDatabase(dbAdminClient, InstanceName.of(database.getInstanceId().getProject(), + database.getInstanceId().getInstance()), database.getDatabase()); break; case "write": writeExampleData(dbClient); @@ -1930,7 +1956,8 @@ static void run( read(dbClient); break; case "addmarketingbudget": - addMarketingBudget(dbAdminClient, database); + addMarketingBudget(dbAdminClient, DatabaseName.of(database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase())); break; case "update": update(dbClient); @@ -1942,7 +1969,8 @@ static void run( queryMarketingBudget(dbClient); break; case "addindex": - addIndex(dbAdminClient, database); + addIndex(dbAdminClient, DatabaseName.of(database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase())); break; case "readindex": readUsingIndex(dbClient); @@ -1951,7 +1979,8 @@ static void run( queryUsingIndex(dbClient); break; case "addstoringindex": - addStoringIndex(dbAdminClient, database); + addStoringIndex(dbAdminClient, DatabaseName.of(database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase())); break; case "readstoringindex": readStoringIndex(dbClient); @@ -1963,7 +1992,8 @@ static void run( readStaleData(dbClient); break; case "addcommittimestamp": - addCommitTimestamp(dbAdminClient, database); + addCommitTimestamp(dbAdminClient, DatabaseName.of(database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase())); break; case "updatewithtimestamp": updateWithTimestamp(dbClient); @@ -1972,7 +2002,9 @@ static void run( queryMarketingBudgetWithTimestamp(dbClient); break; case "createtablewithtimestamp": - createTableWithTimestamp(dbAdminClient, database); + createTableWithTimestamp(dbAdminClient, + DatabaseName.of(database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase())); break; case "writewithtimestamp": writeExampleDataWithTimestamp(dbClient); @@ -2035,7 +2067,9 @@ static void run( updateUsingBatchDml(dbClient); break; case "createtablewithdatatypes": - createTableWithDatatypes(dbAdminClient, database); + createTableWithDatatypes(dbAdminClient, + DatabaseName.of(database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase())); break; case "writedatatypesdata": writeDatatypesData(dbClient); @@ -2074,35 +2108,41 @@ static void run( queryWithQueryOptions(dbClient); break; case "createbackup": - createBackup(dbAdminClient, database, backup, getVersionTime(dbClient)); + createBackup(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase(), + backupId, getVersionTime(dbClient)); break; case "cancelcreatebackup": cancelCreateBackup( dbAdminClient, - database, - BackupId.of(backup.getInstanceId(), backup.getBackup() + "_cancel")); + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase(), + backupId + "_cancel"); break; case "listbackupoperations": - listBackupOperations(instanceAdminClient, database, backup); + listBackupOperations(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase(), backupId); break; case "listdatabaseoperations": - listDatabaseOperations(instanceAdminClient, dbAdminClient, database.getInstanceId()); + listDatabaseOperations(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance()); break; case "listbackups": - listBackups(instanceAdminClient, database, backup); + listBackups(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), database.getDatabase(), backupId); break; case "restorebackup": restoreBackup( - dbAdminClient, - backup, - database, - DatabaseId.of(database.getInstanceId(), createRestoredSampleDbId(database))); + dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), backupId, database.getDatabase()); break; case "updatebackup": - updateBackup(dbAdminClient, backup); + updateBackup(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), backupId); break; case "deletebackup": - deleteBackup(dbAdminClient, backup); + deleteBackup(dbAdminClient, database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), backupId); break; default: printUsageAndExit(); @@ -2111,13 +2151,13 @@ static void run( static Timestamp getVersionTime(DatabaseClient dbClient) { // Generates a version time for the backup - Timestamp versionTime; + com.google.cloud.Timestamp versionTime; try (ResultSet resultSet = dbClient.singleUse() .executeQuery(Statement.of("SELECT CURRENT_TIMESTAMP()"))) { resultSet.next(); versionTime = resultSet.getTimestamp(0); } - return versionTime; + return versionTime.toProto(); } static void printUsageAndExit() { @@ -2185,15 +2225,16 @@ static void printUsageAndExit() { System.exit(1); } - public static void main(String[] args) throws Exception { + public static void main(String[] args) { if (args.length != 3 && args.length != 4) { printUsageAndExit(); } // [START init_client] SpannerOptions options = SpannerOptions.newBuilder().build(); Spanner spanner = options.getService(); + DatabaseAdminClient dbAdminClient = null; try { - String command = args[0]; + final String command = args[0]; DatabaseId db = DatabaseId.of(options.getProjectId(), args[1], args[2]); // [END init_client] // This will return the default project id based on the environment. @@ -2206,25 +2247,26 @@ public static void main(String[] args) throws Exception { printUsageAndExit(); } // Generate a backup id for the sample database. - String backupName = - String.format( - "%s_%02d", - db.getDatabase(), LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR)); - BackupId backup = BackupId.of(db.getInstanceId(), backupName); + String backupId = null; if (args.length == 4) { - backupName = args[3]; + backupId = args[3]; } // [START init_client] DatabaseClient dbClient = spanner.getDatabaseClient(db); - DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + dbAdminClient = spanner.createDatabaseAdminClient(); + // Use client here... // [END init_client] - run(dbClient, dbAdminClient, instanceAdminClient, command, db, backup); + run(dbClient, dbAdminClient, command, db, backupId); // [START init_client] } finally { + if (dbAdminClient != null) { + if (!dbAdminClient.isShutdown() || !dbAdminClient.isTerminated()) { + dbAdminClient.close(); + } + } spanner.close(); } // [END init_client] diff --git a/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseSample.java b/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseSample.java index c87c27690a..57bb8e9159 100644 --- a/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseSample.java @@ -17,15 +17,18 @@ package com.example.spanner; // [START spanner_update_database] + import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.DatabaseInfo.DatabaseField; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.common.collect.Lists; +import com.google.protobuf.FieldMask; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.DatabaseName; import com.google.spanner.admin.database.v1.UpdateDatabaseMetadata; +import com.google.spanner.admin.database.v1.UpdateDatabaseRequest; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -37,22 +40,31 @@ static void updateDatabase() { final String projectId = "my-project"; final String instanceId = "my-instance"; final String databaseId = "my-database"; + updateDatabase(projectId, instanceId, databaseId); } - static void updateDatabase(String projectId, String instanceId, String databaseId) { + static void updateDatabase( + String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); - - DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); - Database databaseToUpdate = - databaseAdminClient.newDatabaseBuilder(dbId).enableDropProtection().build(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + final Database database = + Database.newBuilder() + .setName(DatabaseName.of(projectId, instanceId, databaseId).toString()) + .setEnableDropProtection(true).build(); + final UpdateDatabaseRequest updateDatabaseRequest = + UpdateDatabaseRequest.newBuilder() + .setDatabase(database) + .setUpdateMask( + FieldMask.newBuilder().addAllPaths( + Lists.newArrayList("enable_drop_protection")).build()) + .build(); OperationFuture operation = - databaseAdminClient.updateDatabase(databaseToUpdate, DatabaseField.DROP_PROTECTION); - System.out.printf("Waiting for update operation for %s to complete...\n", dbId); + databaseAdminClient.updateDatabaseAsync(updateDatabaseRequest); + System.out.printf("Waiting for update operation for %s to complete...\n", databaseId); Database updatedDb = operation.get(5, TimeUnit.MINUTES); - System.out.printf("Updated database %s.\n", updatedDb.getId().getName()); + System.out.printf("Updated database %s.\n", updatedDb.getName()); } catch (ExecutionException | TimeoutException e) { // If the operation failed during execution, expose the cause. throw SpannerExceptionFactory.asSpannerException(e.getCause()); diff --git a/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSample.java b/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSample.java index f3ce004a69..701240cb12 100644 --- a/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSample.java @@ -18,13 +18,12 @@ //[START spanner_update_database_with_default_leader] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.DatabaseAdminClient; 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.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.spanner.admin.database.v1.DatabaseName; import java.util.Collections; import java.util.concurrent.ExecutionException; @@ -41,26 +40,20 @@ static void updateDatabaseWithDefaultLeader() { static void updateDatabaseWithDefaultLeader( String projectId, String instanceId, String databaseId, String defaultLeader) { - try (Spanner spanner = SpannerOptions - .newBuilder() - .setProjectId(projectId) - .build() - .getService()) { - final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); - final OperationFuture operation = databaseAdminClient - .updateDatabaseDdl( - instanceId, - databaseId, + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + databaseAdminClient + .updateDatabaseDdlAsync( + DatabaseName.of(projectId, instanceId, databaseId), Collections.singletonList( String.format( "ALTER DATABASE `%s` SET OPTIONS (default_leader = '%s')", databaseId, defaultLeader ) - ), - null - ); - operation.get(); + ) + ).get(); System.out.println("Updated default leader to " + defaultLeader); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. diff --git a/samples/snippets/src/main/java/com/example/spanner/UpdateInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/UpdateInstanceConfigSample.java index 6450f265e1..c10175abe1 100644 --- a/samples/snippets/src/main/java/com/example/spanner/UpdateInstanceConfigSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/UpdateInstanceConfigSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 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. @@ -17,21 +17,21 @@ package com.example.spanner; // [START spanner_update_instance_config] -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceConfig; -import com.google.cloud.spanner.InstanceConfigId; -import com.google.cloud.spanner.InstanceConfigInfo; -import com.google.cloud.spanner.InstanceConfigInfo.InstanceConfigField; + import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.instance.v1.UpdateInstanceConfigMetadata; +import com.google.protobuf.FieldMask; +import com.google.spanner.admin.instance.v1.InstanceConfig; +import com.google.spanner.admin.instance.v1.InstanceConfigName; +import com.google.spanner.admin.instance.v1.UpdateInstanceConfigRequest; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; class UpdateInstanceConfigSample { + static void updateInstanceConfig() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; @@ -41,27 +41,42 @@ static void updateInstanceConfig() { static void updateInstanceConfig(String projectId, String instanceConfigId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { - final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); - InstanceConfigInfo instanceConfigInfo = - InstanceConfig.newBuilder(InstanceConfigId.of(projectId, instanceConfigId)) + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService(); + InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { + final InstanceConfigName instanceConfigName = + InstanceConfigName.of(projectId, instanceConfigId); + final InstanceConfig instanceConfig = + InstanceConfig.newBuilder() + .setName(instanceConfigName.toString()) .setDisplayName("updated custom instance config") - .addLabel("updated", "true") - .build(); - final OperationFuture operation = - instanceAdminClient.updateInstanceConfig( - instanceConfigInfo, - ImmutableList.of(InstanceConfigField.DISPLAY_NAME, InstanceConfigField.LABELS)); + .putLabels("updated", "true").build(); + /** + * The field mask must always be specified; this prevents any future + * fields in [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig] + * from being erased accidentally by clients that do not know about them. + */ + final UpdateInstanceConfigRequest updateInstanceConfigRequest = + UpdateInstanceConfigRequest.newBuilder() + .setInstanceConfig(instanceConfig) + .setUpdateMask( + FieldMask.newBuilder().addAllPaths(ImmutableList.of("display_name", "labels")) + .build()).build(); try { - System.out.printf("Waiting for update operation on %s to complete...\n", instanceConfigId); - InstanceConfig instanceConfig = operation.get(5, TimeUnit.MINUTES); + System.out.printf("Waiting for update operation on %s to complete...\n", + instanceConfigName); + InstanceConfig instanceConfigResult = + instanceAdminClient.updateInstanceConfigAsync( + updateInstanceConfigRequest).get(5, TimeUnit.MINUTES); System.out.printf( "Updated instance configuration %s with new display name %s\n", - instanceConfig.getId(), instanceConfig.getDisplayName()); + instanceConfigResult.getName(), instanceConfig.getDisplayName()); } catch (ExecutionException | TimeoutException e) { System.out.printf( "Error: Updating instance config %s failed with error message %s\n", - instanceConfigInfo.getId(), e.getMessage()); + instanceConfig.getName(), e.getMessage()); e.printStackTrace(); } catch (InterruptedException e) { System.out.println( diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/.gitkeep b/samples/snippets/src/main/java/com/example/spanner/admin/archived/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddAndDropDatabaseRole.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddAndDropDatabaseRole.java new file mode 100644 index 0000000000..cce8543492 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddAndDropDatabaseRole.java @@ -0,0 +1,88 @@ +/* + * 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.archived; + +// [START spanner_add_and_drop_database_role] +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class AddAndDropDatabaseRole { + + static void addAndDropDatabaseRole() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + String parentRole = "my-new-parent-role"; + String childRole = "my-new-child-role"; + addAndDropDatabaseRole(projectId, instanceId, databaseId, parentRole, childRole); + } + + static void addAndDropDatabaseRole( + String projectId, String instanceId, String databaseId, String parentRole, String childRole) { + try (Spanner spanner = + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + OperationFuture operation = + adminClient.updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of( + "CREATE ROLE " + parentRole, + "GRANT SELECT ON TABLE Albums TO ROLE " + parentRole, + "CREATE ROLE " + childRole, + "GRANT ROLE " + parentRole + " TO ROLE " + childRole), + null); + try { + System.out.println("Waiting for role create operation to complete..."); + operation.get(5, TimeUnit.MINUTES); + System.out.printf( + "Created roles %s and %s and granted privileges%n", parentRole, childRole); + // Delete role and membership. + operation = + adminClient.updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of( + "REVOKE ROLE " + parentRole + " FROM ROLE " + childRole, + "DROP ROLE " + childRole), + null); + System.out.println("Waiting for role revoke & drop operation to complete..."); + operation.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] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddJsonColumnSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddJsonColumnSample.java similarity index 55% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/AddJsonColumnSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/AddJsonColumnSample.java index 69d2c229e2..8be7d6bd58 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddJsonColumnSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddJsonColumnSample.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_add_json_column] - +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.concurrent.ExecutionException; class AddJsonColumnSample { @@ -33,24 +33,25 @@ static void addJsonColumn() throws InterruptedException, ExecutionException { String instanceId = "my-instance"; String databaseId = "my-database"; - addJsonColumn(projectId, instanceId, databaseId); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + addJsonColumn(adminClient, instanceId, databaseId); + } } - static void addJsonColumn(String projectId, String instanceId, String databaseId) + static void addJsonColumn(DatabaseAdminClient adminClient, String instanceId, String databaseId) throws InterruptedException, ExecutionException { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - // 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"); - } + OperationFuture operation = + adminClient.updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of("ALTER TABLE Venues ADD COLUMN VenueDetails JSON"), + null); + // Wait for the operation to finish. + // This will throw an ExecutionException if the operation fails. + operation.get(); + System.out.printf("Successfully added column `VenueDetails`%n"); } } // [END spanner_add_json_column] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddJsonbColumnSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddJsonbColumnSample.java similarity index 56% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/AddJsonbColumnSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/AddJsonbColumnSample.java index fa5604e65e..102ea36b0e 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddJsonbColumnSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddJsonbColumnSample.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_postgresql_jsonb_add_column] - +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.concurrent.ExecutionException; class AddJsonbColumnSample { @@ -33,25 +33,25 @@ static void addJsonbColumn() throws InterruptedException, ExecutionException { String instanceId = "my-instance"; String databaseId = "my-database"; - addJsonbColumn(projectId, instanceId, databaseId); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + addJsonbColumn(adminClient, instanceId, databaseId); + } } - static void addJsonbColumn(String projectId, String instanceId, String databaseId) + static void addJsonbColumn(DatabaseAdminClient adminClient, String instanceId, String databaseId) throws InterruptedException, ExecutionException { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - // 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"); - } + OperationFuture operation = + adminClient.updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of("ALTER TABLE Venues ADD COLUMN VenueDetails JSONB"), + null); + // Wait for the operation to finish. + // This will throw an ExecutionException if the operation fails. + operation.get(); + System.out.printf("Successfully added column `VenueDetails`%n"); } } // [END spanner_postgresql_jsonb_add_column] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddNumericColumnSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddNumericColumnSample.java similarity index 55% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/AddNumericColumnSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/AddNumericColumnSample.java index 09f4e63216..347aaf5a9e 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddNumericColumnSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AddNumericColumnSample.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_add_numeric_column] - +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.concurrent.ExecutionException; class AddNumericColumnSample { @@ -33,24 +33,26 @@ static void addNumericColumn() throws InterruptedException, ExecutionException { String instanceId = "my-instance"; String databaseId = "my-database"; - addNumericColumn(projectId, instanceId, databaseId); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + addNumericColumn(adminClient, instanceId, databaseId); + } } - static void addNumericColumn(String projectId, String instanceId, String databaseId) + static void addNumericColumn( + DatabaseAdminClient adminClient, String instanceId, String databaseId) throws InterruptedException, ExecutionException { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - // 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"); - } + OperationFuture operation = + adminClient.updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of("ALTER TABLE Venues ADD COLUMN Revenue NUMERIC"), + null); + // Wait for the operation to finish. + // This will throw an ExecutionException if the operation fails. + operation.get(); + System.out.printf("Successfully added column `Revenue`%n"); } } // [END spanner_add_numeric_column] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AlterSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AlterSequenceSample.java similarity index 89% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/AlterSequenceSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/AlterSequenceSample.java index 08b02b4243..294bfdf6e2 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AlterSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AlterSequenceSample.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_alter_sequence] - +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ResultSet; @@ -25,16 +25,13 @@ 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.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class AlterSequenceSample { - static void alterSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -45,14 +42,17 @@ static void alterSequence() { static void alterSequence(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - databaseAdminClient - .updateDatabaseDdlAsync(DatabaseName.of(projectId, instanceId, databaseId), + dbAdminClient + .updateDatabaseDdl( + instanceId, + databaseId, ImmutableList.of( "ALTER SEQUENCE Seq SET OPTIONS " - + "(skip_range_min = 1000, skip_range_max = 5000000)")) + + "(skip_range_min = 1000, skip_range_max = 5000000)"), + null) .get(5, TimeUnit.MINUTES); System.out.println( diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AlterTableWithForeignKeyDeleteCascadeSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AlterTableWithForeignKeyDeleteCascadeSample.java similarity index 54% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/AlterTableWithForeignKeyDeleteCascadeSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/AlterTableWithForeignKeyDeleteCascadeSample.java index 60f386c75f..ebf8a3f053 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AlterTableWithForeignKeyDeleteCascadeSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/AlterTableWithForeignKeyDeleteCascadeSample.java @@ -14,15 +14,13 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_alter_table_with_foreign_key_delete_cascade] - +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.DatabaseName; class AlterTableWithForeignKeyDeleteCascadeSample { @@ -32,28 +30,30 @@ static void alterForeignKeyDeleteCascadeConstraint() { String instanceId = "my-instance"; String databaseId = "my-database"; - alterForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + alterForeignKeyDeleteCascadeConstraint(adminClient, instanceId, databaseId); + } } static void alterForeignKeyDeleteCascadeConstraint( - String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - 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)); - } + DatabaseAdminClient adminClient, String instanceId, String databaseId) { + adminClient.updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of( + "ALTER TABLE ShoppingCarts\n" + + " ADD CONSTRAINT FKShoppingCartsCustomerName\n" + + " FOREIGN KEY (CustomerName)\n" + + " REFERENCES Customers(CustomerName)\n" + + " ON DELETE CASCADE\n"), + null); + 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] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/CopyBackupSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CopyBackupSample.java new file mode 100644 index 0000000000..3b3c192a5a --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CopyBackupSample.java @@ -0,0 +1,101 @@ +/* + * 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.archived; + +// [START spanner_copy_backup] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Backup; +import com.google.cloud.spanner.BackupId; +import com.google.cloud.spanner.DatabaseAdminClient; +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.spanner.admin.database.v1.CopyBackupMetadata; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +public class CopyBackupSample { + static void copyBackup() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String sourceBackupId = "my-backup"; + String destinationBackupId = "my-destination-backup"; + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + copyBackup(databaseAdminClient, projectId, instanceId, sourceBackupId, destinationBackupId); + } + } + + static void copyBackup( + DatabaseAdminClient databaseAdminClient, + String projectId, + String instanceId, + String sourceBackupId, + String destinationBackupId) { + + Timestamp expireTime = + Timestamp.ofTimeMicroseconds( + TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), + TimeUnit.MILLISECONDS)); + // Creates a copy of an existing backup. + Backup destinationBackup = + databaseAdminClient + .newBackupBuilder(BackupId.of(projectId, instanceId, destinationBackupId)) + .setExpireTime(expireTime) + .build(); + + // Initiate the request which returns an OperationFuture. + System.out.println("Copying backup [" + destinationBackup.getId() + "]..."); + OperationFuture operation = + databaseAdminClient.copyBackup( + BackupId.of(projectId, instanceId, sourceBackupId), destinationBackup); + try { + // Wait for the backup operation to complete. + destinationBackup = operation.get(); + System.out.println("Copied backup [" + destinationBackup.getId() + "]"); + } catch (ExecutionException e) { + throw (SpannerException) e.getCause(); + } catch (InterruptedException e) { + throw SpannerExceptionFactory.propagateInterrupt(e); + } + // Load the metadata of the new backup from the server. + destinationBackup = destinationBackup.reload(); + System.out.println( + String.format( + "Backup %s of size %d bytes was copied at %s for version of database at %s", + destinationBackup.getId().getName(), + destinationBackup.getSize(), + LocalDateTime.ofEpochSecond( + destinationBackup.getProto().getCreateTime().getSeconds(), + destinationBackup.getProto().getCreateTime().getNanos(), + OffsetDateTime.now().getOffset()), + LocalDateTime.ofEpochSecond( + destinationBackup.getProto().getVersionTime().getSeconds(), + destinationBackup.getProto().getVersionTime().getNanos(), + OffsetDateTime.now().getOffset()))); + return; + } +} +// [END spanner_copy_backup] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateBackupWithEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateBackupWithEncryptionKey.java similarity index 58% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateBackupWithEncryptionKey.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateBackupWithEncryptionKey.java index 9152b26a0f..23ddd69917 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateBackupWithEncryptionKey.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateBackupWithEncryptionKey.java @@ -14,22 +14,21 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_create_backup_with_encryption_key] +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Backup; +import com.google.cloud.spanner.BackupId; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.protobuf.Timestamp; -import com.google.spanner.admin.database.v1.Backup; -import com.google.spanner.admin.database.v1.BackupName; -import com.google.spanner.admin.database.v1.CreateBackupEncryptionConfig; -import com.google.spanner.admin.database.v1.CreateBackupEncryptionConfig.EncryptionType; -import com.google.spanner.admin.database.v1.CreateBackupRequest; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.spanner.admin.database.v1.InstanceName; +import com.google.cloud.spanner.encryption.EncryptionConfigs; +import com.google.spanner.admin.database.v1.CreateBackupMetadata; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -38,7 +37,7 @@ public class CreateBackupWithEncryptionKey { - static void createBackupWithEncryptionKey() { + static void createBackupWithEncryptionKey() throws InterruptedException { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; String instanceId = "my-instance"; @@ -48,8 +47,8 @@ static void createBackupWithEncryptionKey() { "projects/" + projectId + "/locations//keyRings//cryptoKeys/"; try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); createBackupWithEncryptionKey( adminClient, projectId, @@ -61,29 +60,24 @@ static void createBackupWithEncryptionKey() { } static Void createBackupWithEncryptionKey(DatabaseAdminClient adminClient, - String projectId, String instanceId, String databaseId, String backupId, String kmsKeyName) { + String projectId, String instanceId, String databaseId, String backupId, String kmsKeyName) + throws InterruptedException { // Set expire time to 14 days from now. - final Timestamp expireTime = - Timestamp.newBuilder().setSeconds(TimeUnit.MILLISECONDS.toSeconds(( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14)))).build(); - final BackupName backupName = BackupName.of(projectId, instanceId, backupId); - Backup backup = Backup.newBuilder() - .setName(backupName.toString()) - .setDatabase(DatabaseName.of(projectId, instanceId, databaseId).toString()) - .setExpireTime(expireTime).build(); + final Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS)); + final Backup backupToCreate = adminClient + .newBackupBuilder(BackupId.of(projectId, instanceId, backupId)) + .setDatabase(DatabaseId.of(projectId, instanceId, databaseId)) + .setExpireTime(expireTime) + .setEncryptionConfig(EncryptionConfigs.customerManagedEncryption(kmsKeyName)) + .build(); + final OperationFuture operation = adminClient + .createBackup(backupToCreate); - final CreateBackupRequest request = - CreateBackupRequest.newBuilder() - .setParent(InstanceName.of(projectId, instanceId).toString()) - .setBackupId(backupId) - .setBackup(backup) - .setEncryptionConfig( - CreateBackupEncryptionConfig.newBuilder() - .setEncryptionType(EncryptionType.CUSTOMER_MANAGED_ENCRYPTION) - .setKmsKeyName(kmsKeyName).build()).build(); + Backup backup; try { System.out.println("Waiting for operation to complete..."); - backup = adminClient.createBackupAsync(request).get(1200, TimeUnit.SECONDS); + backup = operation.get(1200, TimeUnit.SECONDS); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw SpannerExceptionFactory.asSpannerException(e.getCause()); @@ -95,13 +89,14 @@ static Void createBackupWithEncryptionKey(DatabaseAdminClient adminClient, // If the operation timed out propagates the timeout throw SpannerExceptionFactory.propagateTimeout(e); } + System.out.printf( "Backup %s of size %d bytes was created at %s using encryption key %s%n", - backup.getName(), - backup.getSizeBytes(), + backup.getId().getName(), + backup.getSize(), LocalDateTime.ofEpochSecond( - backup.getCreateTime().getSeconds(), - backup.getCreateTime().getNanos(), + backup.getProto().getCreateTime().getSeconds(), + backup.getProto().getCreateTime().getNanos(), OffsetDateTime.now().getOffset()), kmsKeyName ); diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithDefaultLeaderSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithDefaultLeaderSample.java new file mode 100644 index 0000000000..8bfc6422cf --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithDefaultLeaderSample.java @@ -0,0 +1,85 @@ +/* + * 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.example.spanner.admin.archived; + +//[START spanner_create_database_with_default_leader] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +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.spanner.admin.database.v1.CreateDatabaseMetadata; +import java.util.Arrays; +import java.util.concurrent.ExecutionException; + +public class CreateDatabaseWithDefaultLeaderSample { + + static void createDatabaseWithDefaultLeader() { + // TODO(developer): Replace these variables before running the sample. + final String projectId = "my-project"; + final String instanceId = "my-instance"; + final String databaseId = "my-database"; + final String defaultLeader = "my-default-leader"; + createDatabaseWithDefaultLeader(projectId, instanceId, databaseId, defaultLeader); + } + + static void createDatabaseWithDefaultLeader( + String projectId, String instanceId, String databaseId, String defaultLeader) { + try (Spanner spanner = SpannerOptions + .newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + final OperationFuture operation = databaseAdminClient + .createDatabase( + instanceId, + databaseId, + Arrays.asList( + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)", + "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", + "ALTER DATABASE " + "`" + databaseId + "`" + + " SET OPTIONS ( default_leader = '" + defaultLeader + "' )" + ) + ); + final Database database = operation.get(); + System.out.println("Created database [" + database.getId() + "]"); + System.out.println("\tDefault leader: " + database.getDefaultLeader()); + } catch (ExecutionException e) { + // If the operation failed during execution, expose the cause. + throw (SpannerException) 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_create_database_with_default_leader] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateDatabaseWithEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithEncryptionKey.java similarity index 60% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateDatabaseWithEncryptionKey.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithEncryptionKey.java index fe0265409c..2064423547 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateDatabaseWithEncryptionKey.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithEncryptionKey.java @@ -14,19 +14,20 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_create_database_with_encryption_key] +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.EncryptionConfig; -import com.google.spanner.admin.database.v1.InstanceName; +import com.google.cloud.spanner.encryption.EncryptionConfigs; +import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; +import java.util.Arrays; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -42,8 +43,8 @@ static void createDatabaseWithEncryptionKey() { "projects/" + projectId + "/locations//keyRings//cryptoKeys/"; try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); createDatabaseWithEncryptionKey( adminClient, projectId, @@ -55,35 +56,32 @@ static void createDatabaseWithEncryptionKey() { static void createDatabaseWithEncryptionKey(DatabaseAdminClient adminClient, String projectId, String instanceId, String databaseId, String kmsKeyName) { - InstanceName instanceName = InstanceName.of(projectId, instanceId); - CreateDatabaseRequest request = CreateDatabaseRequest.newBuilder() - .setParent(instanceName.toString()) - .setCreateStatement("CREATE DATABASE `" + databaseId + "`") - .setEncryptionConfig(EncryptionConfig.newBuilder().setKmsKeyName(kmsKeyName).build()) - .addAllExtraStatements( - ImmutableList.of( - "CREATE TABLE Singers (" - + " SingerId INT64 NOT NULL," - + " FirstName STRING(1024)," - + " LastName STRING(1024)," - + " SingerInfo BYTES(MAX)" - + ") PRIMARY KEY (SingerId)", - "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" - )) + final Database databaseToCreate = adminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setEncryptionConfig(EncryptionConfigs.customerManagedEncryption(kmsKeyName)) .build(); + final OperationFuture operation = adminClient + .createDatabase(databaseToCreate, Arrays.asList( + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)", + "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" + )); try { System.out.println("Waiting for operation to complete..."); - Database createdDatabase = - adminClient.createDatabaseAsync(request).get(120, TimeUnit.SECONDS); + Database createdDatabase = operation.get(120, TimeUnit.SECONDS); System.out.printf( "Database %s created with encryption key %s%n", - createdDatabase.getName(), + createdDatabase.getId(), createdDatabase.getEncryptionConfig().getKmsKeyName() ); } catch (ExecutionException e) { diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateDatabaseWithVersionRetentionPeriodSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithVersionRetentionPeriodSample.java similarity index 55% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateDatabaseWithVersionRetentionPeriodSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithVersionRetentionPeriodSample.java index fbea541792..1dea5af204 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateDatabaseWithVersionRetentionPeriodSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateDatabaseWithVersionRetentionPeriodSample.java @@ -14,19 +14,19 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_create_database_with_version_retention_period] +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; 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.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.common.collect.Lists; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.InstanceName; +import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; +import java.util.Arrays; import java.util.concurrent.ExecutionException; public class CreateDatabaseWithVersionRetentionPeriodSample { @@ -38,25 +38,39 @@ static void createDatabaseWithVersionRetentionPeriod() { String databaseId = "my-database"; String versionRetentionPeriod = "7d"; - createDatabaseWithVersionRetentionPeriod(projectId, instanceId, databaseId, - versionRetentionPeriod); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + createDatabaseWithVersionRetentionPeriod(adminClient, instanceId, databaseId, + versionRetentionPeriod); + } } - static void createDatabaseWithVersionRetentionPeriod(String projectId, + static void createDatabaseWithVersionRetentionPeriod(DatabaseAdminClient adminClient, String instanceId, String databaseId, String versionRetentionPeriod) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setParent(InstanceName.of(projectId, instanceId).toString()) - .setCreateStatement("CREATE DATABASE `" + databaseId + "`") - .addAllExtraStatements(Lists.newArrayList("ALTER DATABASE " + "`" + databaseId + "`" - + " SET OPTIONS ( version_retention_period = '" + versionRetentionPeriod + "' )")) - .build(); - Database database = - databaseAdminClient.createDatabaseAsync(request).get(); - System.out.println("Created database [" + database.getName() + "]"); + OperationFuture op = + adminClient.createDatabase( + instanceId, + databaseId, + Arrays.asList( + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)", + "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", + "ALTER DATABASE " + "`" + databaseId + "`" + + " SET OPTIONS ( version_retention_period = '" + versionRetentionPeriod + "' )" + )); + try { + Database database = op.get(); + System.out.println("Created database [" + database.getId() + "]"); System.out.println("\tVersion retention period: " + database.getVersionRetentionPeriod()); System.out.println("\tEarliest version time: " + database.getEarliestVersionTime()); } catch (ExecutionException e) { diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceConfigSample.java new file mode 100644 index 0000000000..3b9e49bf0e --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceConfigSample.java @@ -0,0 +1,74 @@ +/* + * 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.admin.archived; + +// [START spanner_create_instance_config] +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceConfig; +import com.google.cloud.spanner.InstanceConfigId; +import com.google.cloud.spanner.InstanceConfigInfo; +import com.google.cloud.spanner.ReplicaInfo; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.instance.v1.CreateInstanceConfigMetadata; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +class CreateInstanceConfigSample { + static void createInstanceConfig() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String baseInstanceConfig = "my-base-instance-config"; + String instanceConfigId = "custom-instance-config4"; + createInstanceConfig(projectId, baseInstanceConfig, instanceConfigId); + } + + static void createInstanceConfig( + String projectId, String baseInstanceConfig, String instanceConfigId) { + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + final InstanceConfig baseConfig = instanceAdminClient.getInstanceConfig(baseInstanceConfig); + List readOnlyReplicas = + ImmutableList.of(baseConfig.getOptionalReplicas().get(0)); + InstanceConfigInfo instanceConfigInfo = + InstanceConfig.newBuilder(InstanceConfigId.of(projectId, instanceConfigId), baseConfig) + .setDisplayName(instanceConfigId) + .addReadOnlyReplicas(readOnlyReplicas) + .build(); + final OperationFuture operation = + instanceAdminClient.createInstanceConfig(instanceConfigInfo); + try { + System.out.printf("Waiting for create operation for %s to complete...\n", instanceConfigId); + InstanceConfig instanceConfig = operation.get(5, TimeUnit.MINUTES); + System.out.printf("Created instance configuration %s\n", instanceConfig.getId()); + } catch (ExecutionException | TimeoutException e) { + System.out.printf( + "Error: Creating instance configuration %s failed with error message %s\n", + instanceConfigInfo.getId(), e.getMessage()); + } catch (InterruptedException e) { + System.out.println( + "Error: Waiting for createInstanceConfig operation to finish was interrupted"); + } + } + } +} +// [END spanner_create_instance_config] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceExample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceExample.java similarity index 56% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceExample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceExample.java index e53b46ede2..15b33ae892 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceExample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 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. @@ -14,17 +14,18 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; //[START spanner_create_instance] - +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.Instance; +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceConfigId; +import com.google.cloud.spanner.InstanceId; +import com.google.cloud.spanner.InstanceInfo; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; -import com.google.spanner.admin.instance.v1.CreateInstanceRequest; -import com.google.spanner.admin.instance.v1.Instance; -import com.google.spanner.admin.instance.v1.InstanceConfigName; -import com.google.spanner.admin.instance.v1.ProjectName; +import com.google.spanner.admin.instance.v1.CreateInstanceMetadata; import java.util.concurrent.ExecutionException; class CreateInstanceExample { @@ -37,41 +38,36 @@ static void createInstance() { } static void createInstance(String projectId, String instanceId) { + Spanner spanner = SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + // Set Instance configuration. + String configId = "regional-us-central1"; int nodeCount = 2; String displayName = "Descriptive name"; - // Create an Instance object that will be used to create the instance. - Instance instance = - Instance.newBuilder() - .setDisplayName(displayName) + // Create an InstanceInfo object that will be used to create the instance. + InstanceInfo instanceInfo = + InstanceInfo.newBuilder(InstanceId.of(projectId, instanceId)) + .setInstanceConfigId(InstanceConfigId.of(projectId, configId)) .setNodeCount(nodeCount) - .setConfig( - InstanceConfigName.of(projectId, "regional-us-central1").toString()) + .setDisplayName(displayName) .build(); - - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - + OperationFuture operation = + instanceAdminClient.createInstance(instanceInfo); + try { // Wait for the createInstance operation to finish. - Instance createdInstance = instanceAdminClient.createInstanceAsync( - CreateInstanceRequest.newBuilder() - .setParent(ProjectName.of(projectId).toString()) - .setInstanceId(instanceId) - .setInstance(instance) - .build()).get(); - System.out.printf("Instance %s was successfully created%n", createdInstance.getName()); + Instance instance = operation.get(); + System.out.printf("Instance %s was successfully created%n", instance.getId()); } catch (ExecutionException e) { System.out.printf( "Error: Creating instance %s failed with error message %s%n", - instance.getName(), e.getMessage()); + instanceInfo.getId(), e.getMessage()); } catch (InterruptedException e) { System.out.println("Error: Waiting for createInstance operation to finish was interrupted"); + } finally { + spanner.close(); } } } -//[END spanner_create_instance] \ No newline at end of file +//[END spanner_create_instance] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigExample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigExample.java new file mode 100644 index 0000000000..3fe60c554b --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigExample.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.example.spanner.admin.archived; + +// [START spanner_create_instance_with_autoscaling_config] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.Instance; +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceConfigId; +import com.google.cloud.spanner.InstanceId; +import com.google.cloud.spanner.InstanceInfo; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.spanner.admin.instance.v1.AutoscalingConfig; +import com.google.spanner.admin.instance.v1.CreateInstanceMetadata; +import java.util.concurrent.ExecutionException; + +class CreateInstanceWithAutoscalingConfigExample { + + static void createInstance() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + createInstance(projectId, instanceId); + } + + static void createInstance(String projectId, String instanceId) { + Spanner spanner = SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + + // Set Instance configuration. + String configId = "regional-us-central1"; + // Create an autoscaling config. + AutoscalingConfig autoscalingConfig = + AutoscalingConfig.newBuilder() + .setAutoscalingLimits( + AutoscalingConfig.AutoscalingLimits.newBuilder().setMinNodes(1).setMaxNodes(2)) + .setAutoscalingTargets( + AutoscalingConfig.AutoscalingTargets.newBuilder() + .setHighPriorityCpuUtilizationPercent(65) + .setStorageUtilizationPercent(95)) + .build(); + + // Create an InstanceInfo object that will be used to create the instance. + InstanceInfo instanceInfo = + InstanceInfo.newBuilder(InstanceId.of(projectId, instanceId)) + .setInstanceConfigId(InstanceConfigId.of(projectId, configId)) + .setAutoscalingConfig(autoscalingConfig) + .setDisplayName("Descriptive name") + .build(); + OperationFuture operation = + instanceAdminClient.createInstance(instanceInfo); + + try { + // Wait for the createInstance operation to finish. + Instance instance = operation.get(); + System.out.printf("Autoscaler instance %s was successfully created%n", instance.getId()); + } catch (ExecutionException e) { + System.out.printf( + "Error: Creating instance %s failed with error message %s%n", + instanceInfo.getId(), e.getMessage()); + } catch (InterruptedException e) { + System.out.println("Error: Waiting for createInstance operation to finish was interrupted"); + } finally { + spanner.close(); + } + } +} +// [END spanner_create_instance_with_autoscaling_config] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithProcessingUnitsExample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithProcessingUnitsExample.java new file mode 100644 index 0000000000..f688b4cdbf --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithProcessingUnitsExample.java @@ -0,0 +1,76 @@ +/* + * 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.example.spanner.admin.archived; + +//[START spanner_create_instance_with_processing_units] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.Instance; +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceConfigId; +import com.google.cloud.spanner.InstanceId; +import com.google.cloud.spanner.InstanceInfo; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.spanner.admin.instance.v1.CreateInstanceMetadata; + +class CreateInstanceWithProcessingUnitsExample { + + static void createInstance() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + createInstance(projectId, instanceId); + } + + static void createInstance(String projectId, String instanceId) { + Spanner spanner = SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + + // Set Instance configuration. + String configId = "regional-us-central1"; + // This will create an instance with the processing power of 0.2 nodes. + int processingUnits = 500; + String displayName = "Descriptive name"; + + try { + // Creates a new instance + System.out.printf("Creating instance %s.%n", instanceId); + OperationFuture operation = + instanceAdminClient.createInstance(InstanceInfo + .newBuilder(InstanceId.of(projectId, instanceId)) + .setInstanceConfigId(InstanceConfigId.of(projectId, configId)) + .setProcessingUnits(processingUnits) + .setDisplayName(displayName) + .build()); + + // Wait for the createInstance operation to finish. + System.out.printf("Waiting for operation on %s to complete...%n", instanceId); + Instance createdInstance = operation.get(); + + System.out.printf("Created instance %s.%n", createdInstance.getId().getInstance()); + + Instance instance = instanceAdminClient.getInstance(instanceId); + System.out.printf("Instance %s has %d processing units.%n", instance.getId().getInstance(), + instance.getProcessingUnits()); + } catch (Exception e) { + System.out.printf("Error: %s.%n", e.getMessage()); + } + spanner.close(); + } +} +//[END spanner_create_instance_with_processing_units] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateSequenceSample.java similarity index 89% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateSequenceSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateSequenceSample.java index d49eacd92e..637bd39d9a 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateSequenceSample.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_create_sequence] - +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ResultSet; @@ -25,16 +25,13 @@ 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.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class CreateSequenceSample { - static void createSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -44,18 +41,20 @@ static void createSequence() { } static void createSequence(String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - databaseAdminClient - .updateDatabaseDdlAsync( - DatabaseName.of(projectId, instanceId, databaseId), + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); + + dbAdminClient + .updateDatabaseDdl( + instanceId, + databaseId, ImmutableList.of( "CREATE SEQUENCE Seq OPTIONS (sequence_kind = 'bit_reversed_positive')", "CREATE TABLE Customers (CustomerId INT64 DEFAULT " + "(GET_NEXT_SEQUENCE_VALUE(SEQUENCE Seq)), CustomerName STRING(1024)) " - + "PRIMARY KEY (CustomerId)")) + + "PRIMARY KEY (CustomerId)"), + null) .get(5, TimeUnit.MINUTES); System.out.println( diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateTableWithForeignKeyDeleteCascadeSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateTableWithForeignKeyDeleteCascadeSample.java new file mode 100644 index 0000000000..a5cc4668d5 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateTableWithForeignKeyDeleteCascadeSample.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.example.spanner.admin.archived; + +// [START spanner_create_table_with_foreign_key_delete_cascade] +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.common.collect.ImmutableList; + +class CreateTableWithForeignKeyDeleteCascadeSample { + + static void createForeignKeyDeleteCascadeConstraint() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + createForeignKeyDeleteCascadeConstraint(adminClient, instanceId, databaseId); + } + } + + static void createForeignKeyDeleteCascadeConstraint( + DatabaseAdminClient adminClient, String instanceId, String databaseId) { + adminClient.updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of( + "CREATE TABLE Customers (\n" + + " CustomerId INT64 NOT NULL,\n" + + " CustomerName STRING(62) NOT NULL,\n" + + " ) PRIMARY KEY (CustomerId)", + "CREATE TABLE ShoppingCarts (\n" + + " CartId INT64 NOT NULL,\n" + + " CustomerId INT64 NOT NULL,\n" + + " CustomerName STRING(62) NOT NULL,\n" + + " CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId)\n" + + " REFERENCES Customers (CustomerId) ON DELETE CASCADE\n" + + " ) PRIMARY KEY (CartId)\n"), + null); + + System.out.printf( + String.format( + "Created Customers and ShoppingCarts table with FKShoppingCartsCustomerId\n" + + "foreign key constraint on database %s on instance %s\n", + databaseId, instanceId)); + } +} +// [END spanner_create_table_with_foreign_key_delete_cascade] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/DeleteInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/DeleteInstanceConfigSample.java similarity index 60% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/DeleteInstanceConfigSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/DeleteInstanceConfigSample.java index 479ca6f2ff..b1013cd4b0 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/DeleteInstanceConfigSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/DeleteInstanceConfigSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Google LLC + * 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. @@ -14,19 +14,15 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_delete_instance_config] - +import com.google.cloud.spanner.InstanceAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; -import com.google.spanner.admin.instance.v1.DeleteInstanceConfigRequest; -import com.google.spanner.admin.instance.v1.InstanceConfigName; class DeleteInstanceConfigSample { - static void deleteInstanceConfig() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; @@ -36,24 +32,16 @@ static void deleteInstanceConfig() { static void deleteInstanceConfig(String projectId, String instanceConfigId) { try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - final InstanceConfigName instanceConfigName = InstanceConfigName.of(projectId, - instanceConfigId); - final DeleteInstanceConfigRequest request = - DeleteInstanceConfigRequest.newBuilder().setName(instanceConfigName.toString()).build(); - + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); try { - System.out.printf("Deleting %s...\n", instanceConfigName); - instanceAdminClient.deleteInstanceConfig(request); - System.out.printf("Deleted instance configuration %s\n", instanceConfigName); + System.out.printf("Deleting %s...\n", instanceConfigId); + instanceAdminClient.deleteInstanceConfig(instanceConfigId); + System.out.printf("Deleted instance configuration %s\n", instanceConfigId); } catch (SpannerException e) { System.out.printf( "Error: Deleting instance configuration %s failed with error message: %s\n", - instanceConfigName, e.getMessage()); + instanceConfigId, e.getMessage()); } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/DropForeignKeyConstraintDeleteCascadeSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/DropForeignKeyConstraintDeleteCascadeSample.java similarity index 58% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/DropForeignKeyConstraintDeleteCascadeSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/DropForeignKeyConstraintDeleteCascadeSample.java index 991216a770..bf03542f91 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/DropForeignKeyConstraintDeleteCascadeSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/DropForeignKeyConstraintDeleteCascadeSample.java @@ -14,15 +14,13 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_drop_foreign_key_constraint_delete_cascade] - +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.DatabaseName; class DropForeignKeyConstraintDeleteCascadeSample { @@ -32,26 +30,28 @@ static void deleteForeignKeyDeleteCascadeConstraint() { String instanceId = "my-instance"; String databaseId = "my-database"; - deleteForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId); + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + deleteForeignKeyDeleteCascadeConstraint(adminClient, instanceId, databaseId); + } } static void deleteForeignKeyDeleteCascadeConstraint( - String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - databaseAdminClient.updateDatabaseDdlAsync( - DatabaseName.of(projectId, instanceId, databaseId), - ImmutableList.of( - "ALTER TABLE ShoppingCarts\n" - + " DROP CONSTRAINT FKShoppingCartsCustomerName\n")); - - System.out.printf( - String.format( - "Altered ShoppingCarts table to drop FKShoppingCartsCustomerName\n" - + "foreign key constraint on database %s on instance %s\n", - databaseId, instanceId)); - } + DatabaseAdminClient adminClient, String instanceId, String databaseId) { + adminClient.updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of( + "ALTER TABLE ShoppingCarts\n" + + " DROP CONSTRAINT FKShoppingCartsCustomerName\n"), + null); + + System.out.printf( + String.format( + "Altered ShoppingCarts table to drop FKShoppingCartsCustomerName\n" + + "foreign key constraint on database %s on instance %s\n", + databaseId, instanceId)); } } // [END spanner_drop_foreign_key_constraint_delete_cascade] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/DropSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/DropSequenceSample.java similarity index 84% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/DropSequenceSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/DropSequenceSample.java index ff3522484f..3e8f2bb414 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/DropSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/DropSequenceSample.java @@ -14,22 +14,19 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_drop_sequence] - +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.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.DatabaseName; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class DropSequenceSample { - static void dropSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -40,14 +37,19 @@ static void dropSequence() { static void dropSequence(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - databaseAdminClient - .updateDatabaseDdlAsync(DatabaseName.of(projectId, instanceId, databaseId), + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); + + dbAdminClient + .updateDatabaseDdl( + instanceId, + databaseId, ImmutableList.of( "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", - "DROP SEQUENCE Seq")) + "DROP SEQUENCE Seq"), + null) .get(5, TimeUnit.MINUTES); + System.out.println( "Altered Customers table to drop DEFAULT from CustomerId column " + "and dropped the Seq sequence"); diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/EnableFineGrainedAccess.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/EnableFineGrainedAccess.java similarity index 63% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/EnableFineGrainedAccess.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/EnableFineGrainedAccess.java index 6538ba87d8..cc373f50f6 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/EnableFineGrainedAccess.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/EnableFineGrainedAccess.java @@ -14,21 +14,16 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_enable_fine_grained_access] - +import com.google.cloud.Binding; +import com.google.cloud.Condition; +import com.google.cloud.Policy; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.iam.v1.Binding; -import com.google.iam.v1.GetIamPolicyRequest; -import com.google.iam.v1.GetPolicyOptions; -import com.google.iam.v1.Policy; -import com.google.iam.v1.SetIamPolicyRequest; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.type.Expr; public class EnableFineGrainedAccess { @@ -51,15 +46,12 @@ static void enableFineGrainedAccess( String title, String role) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - final GetPolicyOptions options = - GetPolicyOptions.newBuilder().setRequestedPolicyVersion(3).build(); - final GetIamPolicyRequest getRequest = - GetIamPolicyRequest.newBuilder() - .setResource(DatabaseName.of(projectId, instanceId, databaseId).toString()) - .setOptions(options).build(); - final Policy policy = databaseAdminClient.getIamPolicy(getRequest); + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + Policy policy = adminClient.getDatabaseIAMPolicy(instanceId, databaseId, 3); int policyVersion = policy.getVersion(); // The policy in the response from getDatabaseIAMPolicy might use the policy version // that you specified, or it might use a lower policy version. For example, if you @@ -73,17 +65,20 @@ static void enableFineGrainedAccess( Binding binding1 = Binding.newBuilder() .setRole("roles/spanner.fineGrainedAccessUser") - .addAllMembers(ImmutableList.of(iamMember)) + .setMembers(ImmutableList.of(iamMember)) .build(); Binding binding2 = Binding.newBuilder() .setRole("roles/spanner.databaseRoleUser") .setCondition( - Expr.newBuilder().setDescription(title).setExpression( - String.format("resource.name.endsWith(\"/databaseRoles/%s\")", role) - ).setTitle(title).build()) - .addAllMembers(ImmutableList.of(iamMember)) + Condition.newBuilder() + .setDescription(title) + .setExpression( + String.format("resource.name.endsWith(\"/databaseRoles/%s\")", role)) + .setTitle(title) + .build()) + .setMembers(ImmutableList.of(iamMember)) .build(); ImmutableList bindings = ImmutableList.builder() @@ -95,13 +90,10 @@ static void enableFineGrainedAccess( Policy.newBuilder() .setVersion(policyVersion) .setEtag(policy.getEtag()) - .addAllBindings(bindings) + .setBindings(bindings) .build(); - final SetIamPolicyRequest setRequest = - SetIamPolicyRequest.newBuilder() - .setResource(DatabaseName.of(projectId, instanceId, databaseId).toString()) - .setPolicy(policyWithConditions).build(); - final Policy response = databaseAdminClient.setIamPolicy(setRequest); + Policy response = + adminClient.setDatabaseIAMPolicy(instanceId, databaseId, policyWithConditions); System.out.printf( "Enabled fine-grained access in IAM with version %d%n", response.getVersion()); } diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/GetDatabaseDdlSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/GetDatabaseDdlSample.java similarity index 67% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/GetDatabaseDdlSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/GetDatabaseDdlSample.java index 5e666ee4f1..c7f56f4969 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/GetDatabaseDdlSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/GetDatabaseDdlSample.java @@ -14,15 +14,14 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; //[START spanner_get_database_ddl] +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.spanner.admin.database.v1.GetDatabaseDdlResponse; +import java.util.List; public class GetDatabaseDdlSample { @@ -36,13 +35,15 @@ static void getDatabaseDdl() { static void getDatabaseDdl( String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - final GetDatabaseDdlResponse response = - databaseAdminClient.getDatabaseDdl(DatabaseName.of(projectId, instanceId, databaseId)); + try (Spanner spanner = SpannerOptions + .newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + final List ddls = databaseAdminClient.getDatabaseDdl(instanceId, databaseId); System.out.println("Retrieved database DDL for " + databaseId); - for (String ddl : response.getStatementsList()) { + for (String ddl : ddls) { System.out.println(ddl); } } diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/GetInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/GetInstanceConfigSample.java similarity index 54% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/GetInstanceConfigSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/GetInstanceConfigSample.java index 334741c3d3..38b6230b97 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/GetInstanceConfigSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/GetInstanceConfigSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Google LLC + * 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. @@ -14,42 +14,39 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; //[START spanner_get_instance_config] +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceConfig; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; -import com.google.spanner.admin.instance.v1.InstanceConfig; -import com.google.spanner.admin.instance.v1.InstanceConfigName; public class GetInstanceConfigSample { static void getInstanceConfig() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; - final String instanceConfigId = "nam6"; - getInstanceConfig(projectId, instanceConfigId); + final String instanceConfigName = "nam6"; + getInstanceConfig(projectId, instanceConfigName); } - static void getInstanceConfig(String projectId, String instanceConfigId) { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - final InstanceConfigName instanceConfigName = InstanceConfigName.of(projectId, - instanceConfigId); + static void getInstanceConfig(String projectId, String instanceConfigName) { + try (Spanner spanner = SpannerOptions + .newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); - final InstanceConfig instanceConfig = - instanceAdminClient.getInstanceConfig(instanceConfigName.toString()); + final InstanceConfig instanceConfig = instanceAdminClient + .getInstanceConfig(instanceConfigName); System.out.printf( "Available leader options for instance config %s: %s%n", - instanceConfig.getName(), - instanceConfig.getLeaderOptionsList() + instanceConfig.getId(), + instanceConfig.getLeaderOptions() ); } } diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListDatabaseRoles.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListDatabaseRoles.java similarity index 54% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/ListDatabaseRoles.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/ListDatabaseRoles.java index 7fea5a9c55..ee31d874ec 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListDatabaseRoles.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListDatabaseRoles.java @@ -14,21 +14,19 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_list_database_roles] - +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.DatabaseRole; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabaseRolesPage; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabaseRolesPagedResponse; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.spanner.admin.database.v1.DatabaseRole; +import java.util.concurrent.ExecutionException; public class ListDatabaseRoles { - static void listDatabaseRoles() { + static void listDatabaseRoles() throws InterruptedException, ExecutionException { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; String instanceId = "my-instance"; @@ -38,16 +36,15 @@ static void listDatabaseRoles() { static void listDatabaseRoles(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - DatabaseName databaseName = DatabaseName.of(projectId, instanceId, databaseId); - ListDatabaseRolesPagedResponse response - = databaseAdminClient.listDatabaseRoles(databaseName); + SpannerOptions.newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); + String databasePath = DatabaseId.of(projectId, instanceId, databaseId).getName(); System.out.println("List of Database roles"); - for (ListDatabaseRolesPage page : response.iteratePages()) { - for (DatabaseRole role : page.iterateAll()) { - System.out.printf("Obtained role %s%n", role.getName()); - } + for (DatabaseRole role : adminClient.listDatabaseRoles(instanceId, databaseId).iterateAll()) { + System.out.printf("%s%n", role.getName()); } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListDatabasesSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListDatabasesSample.java similarity index 61% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/ListDatabasesSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/ListDatabasesSample.java index 703e89b9f1..4abd2c6f25 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListDatabasesSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListDatabasesSample.java @@ -14,17 +14,15 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; //[START spanner_list_databases] +import com.google.api.gax.paging.Page; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabasesPage; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabasesPagedResponse; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.InstanceName; public class ListDatabasesSample { @@ -36,20 +34,21 @@ static void listDatabases() { } static void listDatabases(String projectId, String instanceId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - ListDatabasesPagedResponse response = - databaseAdminClient.listDatabases(InstanceName.of(projectId, instanceId)); - + try (Spanner spanner = SpannerOptions + .newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + Page page = databaseAdminClient.listDatabases(instanceId); System.out.println("Databases for projects/" + projectId + "/instances/" + instanceId); - - for (ListDatabasesPage page : response.iteratePages()) { + while (page != null) { for (Database database : page.iterateAll()) { final String defaultLeader = database.getDefaultLeader().equals("") ? "" : "(default leader = " + database.getDefaultLeader() + ")"; - System.out.println("\t" + database.getName() + " " + defaultLeader); + System.out.println("\t" + database.getId() + " " + defaultLeader); } + page = page.getNextPage(); } } } diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListInstanceConfigOperationsSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListInstanceConfigOperationsSample.java new file mode 100644 index 0000000000..2cf683b4c9 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListInstanceConfigOperationsSample.java @@ -0,0 +1,66 @@ +/* + * 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.admin.archived; + +// [START spanner_list_instance_config_operations] +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.Options; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.longrunning.Operation; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.spanner.admin.instance.v1.CreateInstanceConfigMetadata; + +public class ListInstanceConfigOperationsSample { + static void listInstanceConfigOperations() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + listInstanceConfigOperations(projectId); + } + + static void listInstanceConfigOperations(String projectId) { + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + + try { + System.out.printf( + "Getting list of instance config operations for project %s...\n", + projectId); + final Iterable instanceConfigOperations = + instanceAdminClient + .listInstanceConfigOperations( + Options.filter( + "(metadata.@type=type.googleapis.com/" + + "google.spanner.admin.instance.v1.CreateInstanceConfigMetadata)")) + .iterateAll(); + for (Operation operation : instanceConfigOperations) { + CreateInstanceConfigMetadata metadata = + operation.getMetadata().unpack(CreateInstanceConfigMetadata.class); + System.out.printf( + "Create instance config operation for %s is %d%% completed.\n", + metadata.getInstanceConfig().getName(), metadata.getProgress().getProgressPercent()); + } + } catch (InvalidProtocolBufferException e) { + System.out.printf( + "Error: Listing instance config operations failed with error message %s\n", + e.getMessage()); + } + } + } +} +// [END spanner_list_instance_config_operations] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListInstanceConfigsSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListInstanceConfigsSample.java similarity index 57% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/ListInstanceConfigsSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/ListInstanceConfigsSample.java index f2d6f5fba6..b7753502ba 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListInstanceConfigsSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/ListInstanceConfigsSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Google LLC + * 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. @@ -14,38 +14,36 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; //[START spanner_list_instance_configs] +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceConfig; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; -import com.google.spanner.admin.instance.v1.InstanceConfig; -import com.google.spanner.admin.instance.v1.ProjectName; public class ListInstanceConfigsSample { static void listInstanceConfigs() { // TODO(developer): Replace these variables before running the sample. - String projectId = "my-project"; + final String projectId = "my-project"; listInstanceConfigs(projectId); } static void listInstanceConfigs(String projectId) { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - final ProjectName projectName = ProjectName.of(projectId); - for (InstanceConfig instanceConfig : - instanceAdminClient.listInstanceConfigs(projectName).iterateAll()) { + try (Spanner spanner = SpannerOptions + .newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + + for (InstanceConfig instanceConfig : instanceAdminClient.listInstanceConfigs().iterateAll()) { System.out.printf( "Available leader options for instance config %s: %s%n", - instanceConfig.getName(), - instanceConfig.getLeaderOptionsList() + instanceConfig.getId(), + instanceConfig.getLeaderOptions() ); } } diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgAlterSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgAlterSequenceSample.java similarity index 89% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/PgAlterSequenceSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/PgAlterSequenceSample.java index 1168bdcfad..10bccc2cb4 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgAlterSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgAlterSequenceSample.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_postgresql_alter_sequence] - +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ResultSet; @@ -25,16 +25,13 @@ 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.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class PgAlterSequenceSample { - static void pgAlterSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -45,13 +42,14 @@ static void pgAlterSequence() { static void pgAlterSequence(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - - databaseAdminClient - .updateDatabaseDdlAsync( - DatabaseName.of(projectId, instanceId, databaseId), - ImmutableList.of("ALTER SEQUENCE Seq SKIP RANGE 1000 5000000")) + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); + dbAdminClient + .updateDatabaseDdl( + instanceId, + databaseId, + ImmutableList.of("ALTER SEQUENCE Seq SKIP RANGE 1000 5000000"), + null) .get(5, TimeUnit.MINUTES); System.out.println( "Altered Seq sequence to skip an inclusive range between 1000 and 5000000"); diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgCaseSensitivitySample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgCaseSensitivitySample.java similarity index 79% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/PgCaseSensitivitySample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/PgCaseSensitivitySample.java index 8fbaf6a9c0..a9096c0c2e 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgCaseSensitivitySample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgCaseSensitivitySample.java @@ -14,10 +14,12 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [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; @@ -26,9 +28,7 @@ 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.Lists; -import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.Collections; import java.util.concurrent.ExecutionException; @@ -43,28 +43,34 @@ static void pgCaseSensitivity() { } static void pgCaseSensitivity(String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + 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. - databaseAdminClient.updateDatabaseDdlAsync( - DatabaseName.of(projectId, instanceId, databaseId), - Lists.newArrayList( - "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" - + ")")).get(); + 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)); diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgCreateSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgCreateSequenceSample.java similarity index 88% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/PgCreateSequenceSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/PgCreateSequenceSample.java index 2148427ccd..070f62f70f 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgCreateSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgCreateSequenceSample.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_postgresql_create_sequence] - +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ResultSet; @@ -25,16 +25,13 @@ 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.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class PgCreateSequenceSample { - static void pgCreateSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -45,18 +42,22 @@ static void pgCreateSequence() { static void pgCreateSequence(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - databaseAdminClient - .updateDatabaseDdlAsync(DatabaseName.of(projectId, instanceId, databaseId).toString(), + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); + + dbAdminClient + .updateDatabaseDdl( + instanceId, + databaseId, ImmutableList.of( "CREATE SEQUENCE Seq BIT_REVERSED_POSITIVE;", "CREATE TABLE Customers (CustomerId BIGINT DEFAULT nextval('Seq'), " - + "CustomerName character varying(1024), PRIMARY KEY (CustomerId))")) + + "CustomerName character varying(1024), PRIMARY KEY (CustomerId))"), + null) .get(5, TimeUnit.MINUTES); System.out.println( - "Created Seq sequence and Customers table, where the key column " + "Created Seq sequence and Customers table, where its key column " + "CustomerId uses the sequence as a default value"); final DatabaseClient dbClient = diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgDropSequenceSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgDropSequenceSample.java similarity index 84% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/PgDropSequenceSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/PgDropSequenceSample.java index de856f51a3..26e8eb74bb 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgDropSequenceSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgDropSequenceSample.java @@ -14,22 +14,19 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_postgresql_drop_sequence] - +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.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.DatabaseName; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class PgDropSequenceSample { - static void pgDropSequence() { // TODO(developer): Replace these variables before running the sample. final String projectId = "my-project"; @@ -39,16 +36,17 @@ static void pgDropSequence() { } static void pgDropSequence(String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - databaseAdminClient - .updateDatabaseDdlAsync( - DatabaseName.of(projectId, instanceId, databaseId), + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); + dbAdminClient + .updateDatabaseDdl( + instanceId, + databaseId, ImmutableList.of( "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", - "DROP SEQUENCE Seq")) + "DROP SEQUENCE Seq"), + null) .get(5, TimeUnit.MINUTES); System.out.println( "Altered Customers table to drop DEFAULT from " diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgInterleavedTableSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgInterleavedTableSample.java similarity index 62% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/PgInterleavedTableSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/PgInterleavedTableSample.java index 754920c8dd..007843a4a2 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgInterleavedTableSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgInterleavedTableSample.java @@ -14,15 +14,16 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [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.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.Arrays; import java.util.concurrent.ExecutionException; @@ -37,29 +38,35 @@ static void pgInterleavedTable() { } static void pgInterleavedTable(String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + 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. - databaseAdminClient.updateDatabaseDdlAsync(DatabaseName.of(projectId, + 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")).get(); + 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. diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgSpannerSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgSpannerSample.java similarity index 80% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/PgSpannerSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/PgSpannerSample.java index c4e319c66c..8a95cebef0 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/PgSpannerSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/PgSpannerSample.java @@ -14,18 +14,26 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; +import com.google.api.gax.longrunning.OperationFuture; import com.google.api.gax.paging.Page; import com.google.cloud.ByteArray; import com.google.cloud.Date; import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Instance; +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceId; import com.google.cloud.spanner.Key; import com.google.cloud.spanner.KeyRange; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options; import com.google.cloud.spanner.ReadOnlyTransaction; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Spanner; @@ -37,27 +45,19 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.Value; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListBackupOperationsPagedResponse; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabaseOperationsPagedResponse; import com.google.common.io.BaseEncoding; import com.google.longrunning.Operation; import com.google.protobuf.InvalidProtocolBufferException; -import com.google.spanner.admin.database.v1.BackupName; -import com.google.spanner.admin.database.v1.CopyBackupMetadata; import com.google.spanner.admin.database.v1.CreateBackupMetadata; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.DatabaseDialect; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.spanner.admin.database.v1.ListBackupOperationsRequest; -import com.google.spanner.admin.database.v1.ListDatabaseOperationsRequest; +import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; import com.google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata; -import com.google.spanner.admin.instance.v1.InstanceName; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import com.google.spanner.v1.ExecuteSqlRequest; import java.math.BigDecimal; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -66,7 +66,6 @@ * Example code for using the Cloud Spanner PostgreSQL interface. */ public class PgSpannerSample { - // [START spanner_postgresql_insert_data] static final List SINGERS = Arrays.asList( @@ -84,9 +83,7 @@ public class PgSpannerSample { new Album(2, 3, "Terrified")); // [END spanner_postgresql_insert_data] - /** - * Class to contain performance sample data. - */ + /** Class to contain performance sample data. */ static class Performance { final long singerId; @@ -162,9 +159,7 @@ static class Performance { new BigDecimal("390650.99"))); // [END spanner_postgresql_insert_datatypes_data] - /** - * Class to contain venue sample data. - */ + /** Class to contain venue sample data. */ static class Venue { final long venueId; @@ -200,18 +195,15 @@ static class Venue { } // [START spanner_postgresql_create_database] - static void createPostgreSqlDatabase( - DatabaseAdminClient dbAdminClient, String projectId, String instanceId, String databaseId) { - final CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setCreateStatement("CREATE DATABASE \"" + databaseId + "\"") - .setParent(InstanceName.of(projectId, instanceId).toString()) - .setDatabaseDialect(DatabaseDialect.POSTGRESQL).build(); - + static void createPostgreSqlDatabase(DatabaseAdminClient dbAdminClient, DatabaseId id) { + OperationFuture op = dbAdminClient.createDatabase( + dbAdminClient.newDatabaseBuilder(id).setDialect(Dialect.POSTGRESQL).build(), + Collections.emptyList()); try { // Initiate the request which returns an OperationFuture. - Database db = dbAdminClient.createDatabaseAsync(request).get(); - System.out.println("Created database [" + db.getName() + "]"); + Database db = op.get(); + System.out.println("Created database [" + db.getId() + "]"); + createTableUsingDdl(dbAdminClient, id); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -280,9 +272,9 @@ static void deleteExampleData(DatabaseClient dbClient) { // [START spanner_postgresql_query_data] static void query(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() // Execute a single read or query against Cloud Spanner. - .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) { + dbClient + .singleUse() // Execute a single read or query against Cloud Spanner. + .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), @@ -295,12 +287,12 @@ static void query(DatabaseClient dbClient) { // [START spanner_postgresql_read_data] static void read(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() - .read( - "Albums", - KeySet.all(), // Read all rows in a table. - Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) { + dbClient + .singleUse() + .read( + "Albums", + KeySet.all(), // Read all rows in a table. + Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), @@ -311,12 +303,15 @@ static void read(DatabaseClient dbClient) { // [END spanner_postgresql_read_data] // [START spanner_postgresql_add_column] - static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseName databaseName) { + static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseId dbId) { + OperationFuture op = adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget bigint"), + null); try { // Initiate the request which returns an OperationFuture. - adminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget bigint")).get(); + op.get(); System.out.println("Added MarketingBudget column"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -409,11 +404,11 @@ static void queryMarketingBudget(DatabaseClient dbClient) { // null. A try-with-resource block is used to automatically release resources held by // ResultSet. try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery(Statement.of("SELECT singerid as \"SingerId\", " - + "albumid as \"AlbumId\", marketingbudget as \"MarketingBudget\" " - + "FROM Albums"))) { + dbClient + .singleUse() + .executeQuery(Statement.of("SELECT singerid as \"SingerId\", " + + "albumid as \"AlbumId\", marketingbudget as \"MarketingBudget\" " + + "FROM Albums"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", @@ -429,12 +424,16 @@ static void queryMarketingBudget(DatabaseClient dbClient) { // [END spanner_postgresql_query_data_with_new_column] // [START spanner_postgresql_create_index] - static void addIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) { + static void addIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { + OperationFuture op = + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"), + null); try { // Initiate the request which returns an OperationFuture. - adminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)")).get(); + op.get(); System.out.println("Added AlbumsByAlbumTitle index"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -450,13 +449,13 @@ static void addIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) // [START spanner_postgresql_read_data_with_index] static void readUsingIndex(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() - .readUsingIndex( - "Albums", - "AlbumsByAlbumTitle", - KeySet.all(), - Arrays.asList("AlbumId", "AlbumTitle"))) { + dbClient + .singleUse() + .readUsingIndex( + "Albums", + "AlbumsByAlbumTitle", + KeySet.all(), + Arrays.asList("AlbumId", "AlbumTitle"))) { while (resultSet.next()) { System.out.printf("%d %s\n", resultSet.getLong(0), resultSet.getString(1)); } @@ -465,14 +464,17 @@ static void readUsingIndex(DatabaseClient dbClient) { // [END spanner_postgresql_read_data_with_index] // [START spanner_postgresql_create_storing_index] - static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) { + static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { + OperationFuture op = adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList( + "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " + + "INCLUDE (MarketingBudget)"), + null); try { // Initiate the request which returns an OperationFuture. - adminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList( - "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " - + "INCLUDE (MarketingBudget)")).get(); + op.get(); System.out.println("Added AlbumsByAlbumTitle2 index"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -491,13 +493,13 @@ static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseName databa static void readStoringIndex(DatabaseClient dbClient) { // We can read MarketingBudget also from the index since it stores a copy of MarketingBudget. try (ResultSet resultSet = - dbClient - .singleUse() - .readUsingIndex( - "Albums", - "AlbumsByAlbumTitle2", - KeySet.all(), - Arrays.asList("AlbumId", "AlbumTitle", "MarketingBudget"))) { + dbClient + .singleUse() + .readUsingIndex( + "Albums", + "AlbumsByAlbumTitle2", + KeySet.all(), + Arrays.asList("AlbumId", "AlbumTitle", "MarketingBudget"))) { while (resultSet.next()) { System.out.printf( "%d %s %s\n", @@ -524,8 +526,8 @@ static void readOnlyTransaction(DatabaseClient dbClient) { queryResultSet.getString(2)); } try (ResultSet readResultSet = - transaction.read( - "Albums", KeySet.all(), Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) { + transaction.read( + "Albums", KeySet.all(), Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) { while (readResultSet.next()) { System.out.printf( "%d %d %s\n", @@ -540,10 +542,10 @@ static void readOnlyTransaction(DatabaseClient dbClient) { // [START spanner_postgresql_query_singers_table] static void querySingersTable(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery(Statement.of("SELECT singerid as \"SingerId\", " - + "firstname as \"FirstName\", lastname as \"LastName\" FROM Singers"))) { + dbClient + .singleUse() + .executeQuery(Statement.of("SELECT singerid as \"SingerId\", " + + "firstname as \"FirstName\", lastname as \"LastName\" FROM Singers"))) { while (resultSet.next()) { System.out.printf( "%s %s %s\n", @@ -654,31 +656,35 @@ static void writeWithTransactionUsingDml(DatabaseClient dbClient) { // [START spanner_postgresql_create_table_using_ddl] // [START spanner_postgresql_create_database] - static void createTableUsingDdl(DatabaseAdminClient dbAdminClient, DatabaseName databaseName) { + static void createTableUsingDdl(DatabaseAdminClient dbAdminClient, DatabaseId id) { + OperationFuture op = + dbAdminClient.updateDatabaseDdl( + id.getInstanceId().getInstance(), + id.getDatabase(), + Arrays.asList( + "CREATE TABLE Singers (" + + " SingerId bigint NOT NULL," + + " FirstName character varying(1024)," + + " LastName character varying(1024)," + + " SingerInfo bytea," + + " FullName character varying(2048) GENERATED " + + " ALWAYS AS (FirstName || ' ' || LastName) STORED," + + " PRIMARY KEY (SingerId)" + + ")", + "CREATE TABLE Albums (" + + " SingerId bigint NOT NULL," + + " AlbumId bigint NOT NULL," + + " AlbumTitle character varying(1024)," + + " PRIMARY KEY (SingerId, AlbumId)" + + ") INTERLEAVE IN PARENT Singers ON DELETE CASCADE"), + null); try { // Initiate the request which returns an OperationFuture. - dbAdminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList( - "CREATE TABLE Singers (" - + " SingerId bigint NOT NULL," - + " FirstName character varying(1024)," - + " LastName character varying(1024)," - + " SingerInfo bytea," - + " FullName character varying(2048) GENERATED " - + " ALWAYS AS (FirstName || ' ' || LastName) STORED," - + " PRIMARY KEY (SingerId)" - + ")", - "CREATE TABLE Albums (" - + " SingerId bigint NOT NULL," - + " AlbumId bigint NOT NULL," - + " AlbumTitle character varying(1024)," - + " PRIMARY KEY (SingerId, AlbumId)" - + ") INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).get(); - System.out.println("Created Singers & Albums tables in database: [" + databaseName + "]"); + op.get(); + System.out.println("Created Singers & Albums tables in database: [" + id + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. - throw SpannerExceptionFactory.asSpannerException(e); + throw (SpannerException) 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. @@ -691,11 +697,11 @@ static void createTableUsingDdl(DatabaseAdminClient dbAdminClient, DatabaseName // [START spanner_postgresql_read_stale_data] static void readStaleData(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse(TimestampBound.ofExactStaleness(15, TimeUnit.SECONDS)) - .read( - "Albums", KeySet.all(), - Arrays.asList("SingerId", "AlbumId", "MarketingBudget"))) { + dbClient + .singleUse(TimestampBound.ofExactStaleness(15, TimeUnit.SECONDS)) + .read( + "Albums", KeySet.all(), + Arrays.asList("SingerId", "AlbumId", "MarketingBudget"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", @@ -743,14 +749,17 @@ static void updateWithTimestamp(DatabaseClient dbClient) { // [END spanner_postgresql_update_data_with_timestamp_column] // [START spanner_postgresql_add_timestamp_column] - static void addLastUpdateTimestampColumn( - DatabaseAdminClient adminClient, DatabaseName databaseName) { + static void addLastUpdateTimestampColumn(DatabaseAdminClient adminClient, DatabaseId dbId) { + OperationFuture op = + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList( + "ALTER TABLE Albums ADD COLUMN LastUpdateTime spanner.commit_timestamp"), + null); try { // Initiate the request which returns an OperationFuture. - adminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList( - "ALTER TABLE Albums ADD COLUMN LastUpdateTime spanner.commit_timestamp")).get(); + op.get(); System.out.println("Added LastUpdateTime as a timestamp column in Albums table."); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -769,14 +778,14 @@ static void queryMarketingBudgetWithTimestamp(DatabaseClient dbClient) { // null. A try-with-resource block is used to automatically release resources held by // ResultSet. try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery( - Statement.of( - "SELECT singerid as \"SingerId\", albumid as \"AlbumId\", " - + "marketingbudget as \"MarketingBudget\"," - + "lastupdatetime as \"LastUpdateTime\" FROM Albums" - + " ORDER BY LastUpdateTime DESC"))) { + dbClient + .singleUse() + .executeQuery( + Statement.of( + "SELECT singerid as \"SingerId\", albumid as \"AlbumId\", " + + "marketingbudget as \"MarketingBudget\"," + + "lastupdatetime as \"LastUpdateTime\" FROM Albums" + + " ORDER BY LastUpdateTime DESC"))) { while (resultSet.next()) { System.out.printf( "%d %d %s %s\n", @@ -792,20 +801,24 @@ static void queryMarketingBudgetWithTimestamp(DatabaseClient dbClient) { // [END spanner_postgresql_query_data_with_timestamp_column] // [START spanner_postgresql_create_table_with_timestamp_column] - static void createTableWithTimestamp(DatabaseAdminClient dbAdminClient, - DatabaseName databaseName) { + static void createTableWithTimestamp(DatabaseAdminClient dbAdminClient, DatabaseId id) { + OperationFuture op = + dbAdminClient.updateDatabaseDdl( + id.getInstanceId().getInstance(), + id.getDatabase(), + Arrays.asList( + "CREATE TABLE Performances (" + + " SingerId BIGINT NOT NULL," + + " VenueId BIGINT NOT NULL," + + " Revenue BIGINT," + + " LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL," + + " PRIMARY KEY (SingerId, VenueId))" + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE"), + null); try { // Initiate the request which returns an OperationFuture. - dbAdminClient.updateDatabaseDdlAsync(databaseName, - Arrays.asList( - "CREATE TABLE Performances (" - + " SingerId BIGINT NOT NULL," - + " VenueId BIGINT NOT NULL," - + " Revenue BIGINT," - + " LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL," - + " PRIMARY KEY (SingerId, VenueId))" - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).get(); - System.out.println("Created Performances table in database: [" + databaseName + "]"); + op.get(); + System.out.println("Created Performances table in database: [" + id + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -842,13 +855,13 @@ static void queryPerformancesTable(DatabaseClient dbClient) { // null. A try-with-resource block is used to automatically release resources held by // ResultSet. try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery( - Statement.of( - "SELECT singerid as \"SingerId\", venueid as \"VenueId\", " - + "revenue as \"Revenue\", lastupdatetime as \"LastUpdateTime\" " - + "FROM Performances ORDER BY LastUpdateTime DESC"))) { + dbClient + .singleUse() + .executeQuery( + Statement.of( + "SELECT singerid as \"SingerId\", venueid as \"VenueId\", " + + "revenue as \"Revenue\", lastupdatetime as \"LastUpdateTime\" " + + "FROM Performances ORDER BY LastUpdateTime DESC"))) { while (resultSet.next()) { System.out.printf( "%d %d %s %s\n", @@ -981,24 +994,27 @@ static void updateUsingBatchDml(DatabaseClient dbClient) { // [END spanner_postgresql_dml_batch_update] // [START spanner_postgresql_create_table_with_datatypes] - static void createTableWithDatatypes(DatabaseAdminClient dbAdminClient, - DatabaseName databaseName) { + static void createTableWithDatatypes(DatabaseAdminClient dbAdminClient, DatabaseId id) { + OperationFuture op = + dbAdminClient.updateDatabaseDdl( + id.getInstanceId().getInstance(), + id.getDatabase(), + Arrays.asList( + "CREATE TABLE Venues (" + + " VenueId BIGINT NOT NULL," + + " VenueName character varying(100)," + + " VenueInfo bytea," + + " Capacity BIGINT," + + " OutdoorVenue BOOL, " + + " PopularityScore FLOAT8, " + + " Revenue NUMERIC, " + + " LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL," + + " PRIMARY KEY (VenueId))"), + null); try { // Initiate the request which returns an OperationFuture. - dbAdminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList( - "CREATE TABLE Venues (" - + " VenueId BIGINT NOT NULL," - + " VenueName character varying(100)," - + " VenueInfo bytea," - + " Capacity BIGINT," - + " OutdoorVenue BOOL, " - + " PopularityScore FLOAT8, " - + " Revenue NUMERIC, " - + " LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL," - + " PRIMARY KEY (VenueId))")).get(); - System.out.println("Created Venues table in database: [" + databaseName + "]"); + op.get(); + System.out.println("Created Venues table in database: [" + id + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -1206,9 +1222,9 @@ static void clientWithQueryOptions(DatabaseId db) { Spanner spanner = options.getService(); DatabaseClient dbClient = spanner.getDatabaseClient(db); try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) { + dbClient + .singleUse() + .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2)); @@ -1220,19 +1236,19 @@ static void clientWithQueryOptions(DatabaseId db) { // [START spanner_postgresql_query_with_query_options] static void queryWithQueryOptions(DatabaseClient dbClient) { try (ResultSet resultSet = - dbClient - .singleUse() - .executeQuery( - Statement - .newBuilder("SELECT SingerId, AlbumId, AlbumTitle FROM Albums") - .withQueryOptions(ExecuteSqlRequest.QueryOptions - .newBuilder() - .setOptimizerVersion("1") - // The list of available statistics packages can be found by querying - // the "INFORMATION_SCHEMA.spanner_postgresql_STATISTICS" table. - .setOptimizerStatisticsPackage("latest") - .build()) - .build())) { + dbClient + .singleUse() + .executeQuery( + Statement + .newBuilder("SELECT SingerId, AlbumId, AlbumTitle FROM Albums") + .withQueryOptions(ExecuteSqlRequest.QueryOptions + .newBuilder() + .setOptimizerVersion("1") + // The list of available statistics packages can be found by querying + // the "INFORMATION_SCHEMA.spanner_postgresql_STATISTICS" table. + .setOptimizerStatisticsPackage("latest") + .build()) + .build())) { while (resultSet.next()) { System.out.printf( "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2)); @@ -1242,26 +1258,22 @@ static void queryWithQueryOptions(DatabaseClient dbClient) { // [END spanner_postgresql_query_with_query_options] // [START spanner_postgresql_list_backup_operations] - static void listBackupOperations( - DatabaseAdminClient databaseAdminClient, - String projectId, String instanceId, - String databaseId, String backupId) { - com.google.spanner.admin.database.v1.InstanceName instanceName = - com.google.spanner.admin.database.v1.InstanceName.of(projectId, instanceId); - // Get 'CreateBackup' operations for the sample database. + static void listBackupOperations(InstanceAdminClient instanceAdminClient, DatabaseId databaseId) { + Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance()); + // Get create backup operations for the sample database. + Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert( + TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, + TimeUnit.HOURS), 0); String filter = String.format( - "(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.CreateBackupMetadata) " - + "AND (metadata.database:%s)", - DatabaseName.of(projectId, instanceId, databaseId).toString()); - ListBackupOperationsRequest listBackupOperationsRequest = - ListBackupOperationsRequest.newBuilder() - .setParent(instanceName.toString()).setFilter(filter).build(); - ListBackupOperationsPagedResponse createBackupOperations - = databaseAdminClient.listBackupOperations(listBackupOperationsRequest); - System.out.println("Create Backup Operations:"); - for (Operation op : createBackupOperations.iterateAll()) { + "(metadata.database:%s) AND " + + "(metadata.@type:type.googleapis.com/" + + "google.spanner.admin.database.v1.CreateBackupMetadata) AND " + + "(metadata.progress.start_time > \"%s\")", + databaseId.getName(), last24Hours); + Page operations = instance + .listBackupOperations(Options.filter(filter)); + for (com.google.longrunning.Operation op : operations.iterateAll()) { try { CreateBackupMetadata metadata = op.getMetadata().unpack(CreateBackupMetadata.class); System.out.println( @@ -1275,55 +1287,23 @@ static void listBackupOperations( System.err.println(e.getMessage()); } } - // Get copy backup operations for the sample database. - filter = String.format( - "(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.CopyBackupMetadata) " - + "AND (metadata.source_backup:%s)", - BackupName.of(projectId, instanceId, backupId).toString()); - listBackupOperationsRequest = - ListBackupOperationsRequest.newBuilder() - .setParent(instanceName.toString()).setFilter(filter).build(); - ListBackupOperationsPagedResponse copyBackupOperations = - databaseAdminClient.listBackupOperations(listBackupOperationsRequest); - System.out.println("Copy Backup Operations:"); - for (Operation op : copyBackupOperations.iterateAll()) { - try { - CopyBackupMetadata copyBackupMetadata = - op.getMetadata().unpack(CopyBackupMetadata.class); - System.out.println( - String.format( - "Copy Backup %s on backup %s pending: %d%% complete", - copyBackupMetadata.getName(), - copyBackupMetadata.getSourceBackup(), - copyBackupMetadata.getProgress().getProgressPercent())); - } catch (InvalidProtocolBufferException e) { - // The returned operation does not contain CopyBackupMetadata. - System.err.println(e.getMessage()); - } - } } // [END spanner_postgresql_list_backup_operations] // [START spanner_postgresql_list_database_operations] static void listDatabaseOperations( - DatabaseAdminClient dbAdminClient, String projectId, String instanceId) { + InstanceAdminClient instanceAdminClient, + DatabaseAdminClient dbAdminClient, + InstanceId instanceId) { + Instance instance = instanceAdminClient.getInstance(instanceId.getInstance()); // Get optimize restored database operations. - com.google.cloud.Timestamp last24Hours = com.google.cloud.Timestamp.ofTimeSecondsAndNanos( - TimeUnit.SECONDS.convert( - TimeUnit.HOURS.convert(com.google.cloud.Timestamp.now().getSeconds(), TimeUnit.SECONDS) - - 24, - TimeUnit.HOURS), 0); + Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert( + TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, + TimeUnit.HOURS), 0); String filter = String.format("(metadata.@type:type.googleapis.com/" + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) AND " + "(metadata.progress.start_time > \"%s\")", last24Hours); - ListDatabaseOperationsRequest listDatabaseOperationsRequest = - ListDatabaseOperationsRequest.newBuilder() - .setParent(com.google.spanner.admin.instance.v1.InstanceName.of( - projectId, instanceId).toString()).setFilter(filter).build(); - ListDatabaseOperationsPagedResponse pagedResponse - = dbAdminClient.listDatabaseOperations(listDatabaseOperationsRequest); - for (Operation op : pagedResponse.iterateAll()) { + for (Operation op : instance.listDatabaseOperations(Options.filter(filter)).iterateAll()) { try { OptimizeRestoredDatabaseMetadata metadata = op.getMetadata().unpack(OptimizeRestoredDatabaseMetadata.class); @@ -1342,15 +1322,12 @@ static void listDatabaseOperations( static void run( DatabaseClient dbClient, DatabaseAdminClient dbAdminClient, + InstanceAdminClient instanceAdminClient, String command, - DatabaseId database, - String backupId) { - DatabaseName databaseName = DatabaseName.of(database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase()); + DatabaseId database) { switch (command) { - case "createpgdatabase": - createPostgreSqlDatabase(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase()); + case "createdatabase": + createPostgreSqlDatabase(dbAdminClient, database); break; case "write": writeExampleData(dbClient); @@ -1365,7 +1342,7 @@ static void run( read(dbClient); break; case "addmarketingbudget": - addMarketingBudget(dbAdminClient, databaseName); + addMarketingBudget(dbAdminClient, database); break; case "update": update(dbClient); @@ -1377,13 +1354,13 @@ static void run( queryMarketingBudget(dbClient); break; case "addindex": - addIndex(dbAdminClient, databaseName); + addIndex(dbAdminClient, database); break; case "readindex": readUsingIndex(dbClient); break; case "addstoringindex": - addStoringIndex(dbAdminClient, databaseName); + addStoringIndex(dbAdminClient, database); break; case "readstoringindex": readStoringIndex(dbClient); @@ -1404,13 +1381,13 @@ static void run( writeWithTransactionUsingDml(dbClient); break; case "createtableusingddl": - createTableUsingDdl(dbAdminClient, databaseName); + createTableUsingDdl(dbAdminClient, database); break; case "readstaledata": readStaleData(dbClient); break; case "addlastupdatetimestampcolumn": - addLastUpdateTimestampColumn(dbAdminClient, databaseName); + addLastUpdateTimestampColumn(dbAdminClient, database); break; case "updatewithtimestamp": updateWithTimestamp(dbClient); @@ -1419,7 +1396,7 @@ static void run( queryMarketingBudgetWithTimestamp(dbClient); break; case "createtablewithtimestamp": - createTableWithTimestamp(dbAdminClient, databaseName); + createTableWithTimestamp(dbAdminClient, database); break; case "writewithtimestamp": writeExampleDataWithTimestamp(dbClient); @@ -1449,7 +1426,7 @@ static void run( updateUsingBatchDml(dbClient); break; case "createtablewithdatatypes": - createTableWithDatatypes(dbAdminClient, databaseName); + createTableWithDatatypes(dbAdminClient, database); break; case "writedatatypesdata": writeDatatypesData(dbClient); @@ -1482,12 +1459,10 @@ static void run( queryWithQueryOptions(dbClient); break; case "listbackupoperations": - listBackupOperations(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase(), backupId); + listBackupOperations(instanceAdminClient, database); break; case "listdatabaseoperations": - listDatabaseOperations(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance()); + listDatabaseOperations(instanceAdminClient, dbAdminClient, database.getInstanceId()); break; default: printUsageAndExit(); @@ -1550,10 +1525,9 @@ public static void main(String[] args) { // [START spanner_init_client] SpannerOptions options = SpannerOptions.newBuilder().build(); Spanner spanner = options.getService(); - DatabaseAdminClient dbAdminClient = null; try { // [END spanner_init_client] - final String command = args[0]; + String command = args[0]; DatabaseId db = DatabaseId.of(options.getProjectId(), args[1], args[2]); // This will return the default project id based on the environment. @@ -1565,35 +1539,23 @@ public static void main(String[] args) { + clientProject); printUsageAndExit(); } - // Generate a backup id for the sample database. - String backupId = null; - if (args.length == 4) { - backupId = args[3]; - } - // [START spanner_init_client] DatabaseClient dbClient = spanner.getDatabaseClient(db); - dbAdminClient = spanner.createDatabaseAdminClient(); + DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); + InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); // [END spanner_init_client] // Use client here... - run(dbClient, dbAdminClient, command, db, backupId); + run(dbClient, dbAdminClient, instanceAdminClient, command, db); // [START spanner_init_client] } finally { - if (dbAdminClient != null) { - if (!dbAdminClient.isShutdown() || !dbAdminClient.isTerminated()) { - dbAdminClient.close(); - } - } spanner.close(); } // [END spanner_init_client] System.out.println("Closed client"); } - /** - * Class to contain singer sample data. - */ + /** Class to contain singer sample data. */ static class Singer { final long singerId; @@ -1607,9 +1569,7 @@ static class Singer { } } - /** - * Class to contain album sample data. - */ + /** Class to contain album sample data. */ static class Album { final long singerId; diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/RestoreBackupWithEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/RestoreBackupWithEncryptionKey.java similarity index 65% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/RestoreBackupWithEncryptionKey.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/RestoreBackupWithEncryptionKey.java index 3c129860f0..087413dbe5 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/RestoreBackupWithEncryptionKey.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/RestoreBackupWithEncryptionKey.java @@ -14,21 +14,21 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_restore_backup_with_encryption_key] -import static com.google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION; - +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.BackupId; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Restore; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.spanner.admin.database.v1.BackupName; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.InstanceName; -import com.google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig; -import com.google.spanner.admin.database.v1.RestoreDatabaseRequest; +import com.google.cloud.spanner.encryption.EncryptionConfigs; +import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata; import java.util.concurrent.ExecutionException; public class RestoreBackupWithEncryptionKey { @@ -43,8 +43,8 @@ static void restoreBackupWithEncryptionKey() { "projects/" + projectId + "/locations//keyRings//cryptoKeys/"; try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient(); restoreBackupWithEncryptionKey( adminClient, projectId, @@ -57,18 +57,19 @@ static void restoreBackupWithEncryptionKey() { static Void restoreBackupWithEncryptionKey(DatabaseAdminClient adminClient, String projectId, String instanceId, String backupId, String restoreId, String kmsKeyName) { - RestoreDatabaseRequest request = - RestoreDatabaseRequest.newBuilder() - .setParent(InstanceName.of(projectId, instanceId).toString()) - .setDatabaseId(restoreId) - .setBackup(BackupName.of(projectId, instanceId, backupId).toString()) - .setEncryptionConfig(RestoreDatabaseEncryptionConfig.newBuilder() - .setEncryptionType(CUSTOMER_MANAGED_ENCRYPTION).setKmsKeyName(kmsKeyName)).build(); + final Restore restore = adminClient + .newRestoreBuilder( + BackupId.of(projectId, instanceId, backupId), + DatabaseId.of(projectId, instanceId, restoreId)) + .setEncryptionConfig(EncryptionConfigs.customerManagedEncryption(kmsKeyName)) + .build(); + final OperationFuture operation = adminClient + .restoreDatabase(restore); + Database database; try { System.out.println("Waiting for operation to complete..."); - database = adminClient.restoreDatabaseAsync(request).get(); - ; + database = operation.get(); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw SpannerExceptionFactory.asSpannerException(e.getCause()); @@ -80,9 +81,9 @@ static Void restoreBackupWithEncryptionKey(DatabaseAdminClient adminClient, System.out.printf( "Database %s restored to %s from backup %s using encryption key %s%n", - database.getRestoreInfo().getBackupInfo().getSourceDatabase(), - database.getName(), - database.getRestoreInfo().getBackupInfo().getBackup(), + database.getRestoreInfo().getSourceDatabase(), + database.getId(), + database.getRestoreInfo().getBackup(), database.getEncryptionConfig().getKmsKeyName() ); return null; diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/SpannerSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/SpannerSample.java similarity index 79% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/SpannerSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/SpannerSample.java index 7cc4af7c74..98eba6d944 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/SpannerSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/SpannerSample.java @@ -14,25 +14,34 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static com.google.cloud.spanner.Type.StructField; import com.google.api.gax.longrunning.OperationFuture; import com.google.api.gax.longrunning.OperationSnapshot; +import com.google.api.gax.paging.Page; import com.google.api.gax.retrying.RetryingFuture; -import com.google.api.gax.rpc.NotFoundException; import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StatusCode.Code; import com.google.cloud.ByteArray; import com.google.cloud.Date; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Backup; +import com.google.cloud.spanner.BackupId; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Instance; +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceId; import com.google.cloud.spanner.Key; import com.google.cloud.spanner.KeyRange; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options; import com.google.cloud.spanner.ReadOnlyTransaction; +import com.google.cloud.spanner.RestoreInfo; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerBatchUpdateException; @@ -44,41 +53,27 @@ import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Value; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListBackupOperationsPagedResponse; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListBackupsPagedResponse; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient.ListDatabaseOperationsPagedResponse; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; import com.google.common.io.BaseEncoding; import com.google.longrunning.Operation; -import com.google.protobuf.FieldMask; import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.Timestamp; -import com.google.spanner.admin.database.v1.Backup; -import com.google.spanner.admin.database.v1.BackupInfo; -import com.google.spanner.admin.database.v1.BackupName; import com.google.spanner.admin.database.v1.CopyBackupMetadata; import com.google.spanner.admin.database.v1.CreateBackupMetadata; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.spanner.admin.database.v1.InstanceName; -import com.google.spanner.admin.database.v1.ListBackupOperationsRequest; -import com.google.spanner.admin.database.v1.ListBackupsRequest; -import com.google.spanner.admin.database.v1.ListDatabaseOperationsRequest; +import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; import com.google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata; import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata; -import com.google.spanner.admin.database.v1.RestoreDatabaseRequest; -import com.google.spanner.admin.database.v1.RestoreInfo; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.math.BigDecimal; import java.time.Instant; -import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import org.threeten.bp.LocalDate; +import org.threeten.bp.LocalDateTime; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.temporal.ChronoField; /** * Example code for using the Cloud Spanner API. This example demonstrates all the common operations @@ -98,9 +93,7 @@ */ public class SpannerSample { - /** - * Class to contain singer sample data. - */ + /** Class to contain singer sample data. */ static class Singer { final long singerId; @@ -114,9 +107,7 @@ static class Singer { } } - /** - * Class to contain album sample data. - */ + /** Class to contain album sample data. */ static class Album { final long singerId; @@ -130,9 +121,7 @@ static class Album { } } - /** - * Class to contain performance sample data. - */ + /** Class to contain performance sample data. */ static class Performance { final long singerId; @@ -148,9 +137,7 @@ static class Performance { } } - /** - * Class to contain venue sample data. - */ + /** Class to contain venue sample data. */ static class Venue { final long venueId; @@ -188,6 +175,17 @@ static class Venue { } } + /** Get a database id to restore a backup to from the sample database id. */ + static String createRestoredSampleDbId(DatabaseId database) { + int index = database.getDatabase().indexOf('-'); + String prefix = database.getDatabase().substring(0, index); + String restoredDbId = database.getDatabase().replace(prefix, "restored"); + if (restoredDbId.length() > 30) { + restoredDbId = restoredDbId.substring(0, 30); + } + return restoredDbId; + } + // [START spanner_insert_data] static final List SINGERS = Arrays.asList( @@ -274,13 +272,12 @@ static class Venue { // [END spanner_insert_datatypes_data] // [START spanner_create_database] - static void createDatabase(DatabaseAdminClient dbAdminClient, - InstanceName instanceName, String databaseId) { - CreateDatabaseRequest createDatabaseRequest = - CreateDatabaseRequest.newBuilder() - .setCreateStatement("CREATE DATABASE `" + databaseId + "`") - .setParent(instanceName.toString()) - .addAllExtraStatements(Arrays.asList( + static void createDatabase(DatabaseAdminClient dbAdminClient, DatabaseId id) { + OperationFuture op = + dbAdminClient.createDatabase( + id.getInstanceId().getInstance(), + id.getDatabase(), + Arrays.asList( "CREATE TABLE Singers (" + " SingerId INT64 NOT NULL," + " FirstName STRING(1024)," @@ -294,12 +291,11 @@ static void createDatabase(DatabaseAdminClient dbAdminClient, + " AlbumId INT64 NOT NULL," + " AlbumTitle STRING(MAX)" + ") PRIMARY KEY (SingerId, AlbumId)," - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).build(); + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")); try { // Initiate the request which returns an OperationFuture. - com.google.spanner.admin.database.v1.Database db = - dbAdminClient.createDatabaseAsync(createDatabaseRequest).get(); - System.out.println("Created database [" + db.getName() + "]"); + Database db = op.get(); + System.out.println("Created database [" + db.getId() + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -312,23 +308,25 @@ static void createDatabase(DatabaseAdminClient dbAdminClient, // [END spanner_create_database] // [START spanner_create_table_with_timestamp_column] - static void createTableWithTimestamp(DatabaseAdminClient dbAdminClient, - DatabaseName databaseName) { + static void createTableWithTimestamp(DatabaseAdminClient dbAdminClient, DatabaseId id) { + OperationFuture op = + dbAdminClient.updateDatabaseDdl( + id.getInstanceId().getInstance(), + id.getDatabase(), + Arrays.asList( + "CREATE TABLE Performances (" + + " SingerId INT64 NOT NULL," + + " VenueId INT64 NOT NULL," + + " EventDate Date," + + " Revenue INT64, " + + " LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)" + + ") PRIMARY KEY (SingerId, VenueId, EventDate)," + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE"), + null); try { // Initiate the request which returns an OperationFuture. - dbAdminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList( - "CREATE TABLE Performances (" - + " SingerId INT64 NOT NULL," - + " VenueId INT64 NOT NULL," - + " EventDate Date," - + " Revenue INT64, " - + " LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)" - + ") PRIMARY KEY (SingerId, VenueId, EventDate)," - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).get(); - System.out.println( - "Created Performances table in database: [" + databaseName.toString() + "]"); + op.get(); + System.out.println("Created Performances table in database: [" + id + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -448,12 +446,16 @@ static void read(DatabaseClient dbClient) { // [END spanner_read_data] // [START spanner_add_column] - static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseName databaseName) { + static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseId dbId) { + OperationFuture op = + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"), + null); try { // Initiate the request which returns an OperationFuture. - adminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64")).get(); + op.get(); System.out.println("Added MarketingBudget column"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -563,12 +565,16 @@ static void queryMarketingBudget(DatabaseClient dbClient) { // [END spanner_query_data_with_new_column] // [START spanner_create_index] - static void addIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) { + static void addIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { + OperationFuture op = + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"), + null); try { // Initiate the request which returns an OperationFuture. - adminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)")).get(); + op.get(); System.out.println("Added AlbumsByAlbumTitle index"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -630,14 +636,18 @@ static void readUsingIndex(DatabaseClient dbClient) { // [END spanner_read_data_with_index] // [START spanner_create_storing_index] - static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseName databaseName) { + static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { + OperationFuture op = + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList( + "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " + + "STORING (MarketingBudget)"), + null); try { // Initiate the request which returns an OperationFuture. - adminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList( - "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " - + "STORING (MarketingBudget)")).get(); + op.get(); System.out.println("Added AlbumsByAlbumTitle2 index"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -719,14 +729,18 @@ static void readStaleData(DatabaseClient dbClient) { // [END spanner_read_stale_data] // [START spanner_add_timestamp_column] - static void addCommitTimestamp(DatabaseAdminClient adminClient, DatabaseName databaseName) { + static void addCommitTimestamp(DatabaseAdminClient adminClient, DatabaseId dbId) { + OperationFuture op = + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList( + "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " + + "OPTIONS (allow_commit_timestamp=true)"), + null); try { // Initiate the request which returns an OperationFuture. - adminClient.updateDatabaseDdlAsync( - databaseName, - Arrays.asList( - "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " - + "OPTIONS (allow_commit_timestamp=true)")).get(); + op.get(); System.out.println("Added LastUpdateTime as a commit timestamp column in Albums table."); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. @@ -1172,18 +1186,18 @@ static void writeWithTransactionUsingDml(DatabaseClient dbClient) { album2Budget -= transfer; Statement updateStatement = Statement.newBuilder( - "UPDATE Albums " - + "SET MarketingBudget = @AlbumBudget " - + "WHERE SingerId = 1 and AlbumId = 1") + "UPDATE Albums " + + "SET MarketingBudget = @AlbumBudget " + + "WHERE SingerId = 1 and AlbumId = 1") .bind("AlbumBudget") .to(album1Budget) .build(); transaction.executeUpdate(updateStatement); Statement updateStatement2 = Statement.newBuilder( - "UPDATE Albums " - + "SET MarketingBudget = @AlbumBudget " - + "WHERE SingerId = 2 and AlbumId = 2") + "UPDATE Albums " + + "SET MarketingBudget = @AlbumBudget " + + "WHERE SingerId = 2 and AlbumId = 2") .bind("AlbumBudget") .to(album2Budget) .build(); @@ -1241,26 +1255,30 @@ static void updateUsingBatchDml(DatabaseClient dbClient) { // [END spanner_dml_batch_update] // [START spanner_create_table_with_datatypes] - static void createTableWithDatatypes(DatabaseAdminClient dbAdminClient, - DatabaseName databaseName) { + static void createTableWithDatatypes(DatabaseAdminClient dbAdminClient, DatabaseId id) { + OperationFuture op = + dbAdminClient.updateDatabaseDdl( + id.getInstanceId().getInstance(), + id.getDatabase(), + Arrays.asList( + "CREATE TABLE Venues (" + + " VenueId INT64 NOT NULL," + + " VenueName STRING(100)," + + " VenueInfo BYTES(MAX)," + + " Capacity INT64," + + " AvailableDates ARRAY," + + " LastContactDate DATE," + + " OutdoorVenue BOOL, " + + " PopularityScore FLOAT64, " + + " Revenue NUMERIC, " + + " VenueDetails JSON, " + + " LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)" + + ") PRIMARY KEY (VenueId)"), + null); try { // Initiate the request which returns an OperationFuture. - dbAdminClient.updateDatabaseDdlAsync(databaseName, - Arrays.asList( - "CREATE TABLE Venues (" - + " VenueId INT64 NOT NULL," - + " VenueName STRING(100)," - + " VenueInfo BYTES(MAX)," - + " Capacity INT64," - + " AvailableDates ARRAY," - + " LastContactDate DATE," - + " OutdoorVenue BOOL, " - + " PopularityScore FLOAT64, " - + " Revenue NUMERIC, " - + " VenueDetails JSON, " - + " LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)" - + ") PRIMARY KEY (VenueId)")).get(); - System.out.println("Created Venues table in database: [" + databaseName.toString() + "]"); + op.get(); + System.out.println("Created Venues table in database: [" + id + "]"); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. throw (SpannerException) e.getCause(); @@ -1552,76 +1570,74 @@ static void queryWithQueryOptions(DatabaseClient dbClient) { // [END spanner_query_with_query_options] // [START spanner_create_backup] - static void createBackup(DatabaseAdminClient dbAdminClient, String projectId, String instanceId, - String databaseId, String backupId, Timestamp versionTime) { + static void createBackup(DatabaseAdminClient dbAdminClient, DatabaseId databaseId, + BackupId backupId, Timestamp versionTime) { // Set expire time to 14 days from now. - Timestamp expireTime = - Timestamp.newBuilder().setSeconds(TimeUnit.MILLISECONDS.toSeconds(( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14)))).build(); - BackupName backupName = BackupName.of(projectId, instanceId, backupId); - Backup backup = Backup.newBuilder() - .setName(backupName.toString()) - .setDatabase(DatabaseName.of(projectId, instanceId, databaseId).toString()) - .setExpireTime(expireTime).setVersionTime(versionTime).build(); - + Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS)); + Backup backup = + dbAdminClient + .newBackupBuilder(backupId) + .setDatabase(databaseId) + .setExpireTime(expireTime) + .setVersionTime(versionTime) + .build(); // Initiate the request which returns an OperationFuture. - System.out.println("Creating backup [" + backupId + "]..."); + System.out.println("Creating backup [" + backup.getId() + "]..."); + OperationFuture op = backup.create(); try { // Wait for the backup operation to complete. - backup = dbAdminClient.createBackupAsync( - InstanceName.of(projectId, instanceId), backup, backupId).get(); - System.out.println("Created backup [" + backup.getName() + "]"); + backup = op.get(); + System.out.println("Created backup [" + backup.getId() + "]"); } catch (ExecutionException e) { - throw SpannerExceptionFactory.asSpannerException(e); + throw (SpannerException) e.getCause(); } catch (InterruptedException e) { throw SpannerExceptionFactory.propagateInterrupt(e); } // Reload the metadata of the backup from the server. - backup = dbAdminClient.getBackup(backup.getName()); + backup = backup.reload(); System.out.println( String.format( "Backup %s of size %d bytes was created at %s for version of database at %s", - backup.getName(), - backup.getSizeBytes(), - java.time.OffsetDateTime.ofInstant( - Instant.ofEpochSecond(backup.getCreateTime().getSeconds(), - backup.getCreateTime().getNanos()), ZoneId.systemDefault()), - java.time.OffsetDateTime.ofInstant( - Instant.ofEpochSecond(backup.getVersionTime().getSeconds(), - backup.getVersionTime().getNanos()), ZoneId.systemDefault())) - ); + backup.getId().getName(), + backup.getSize(), + LocalDateTime.ofEpochSecond( + backup.getProto().getCreateTime().getSeconds(), + backup.getProto().getCreateTime().getNanos(), + OffsetDateTime.now().getOffset()), + LocalDateTime.ofEpochSecond( + backup.getProto().getVersionTime().getSeconds(), + backup.getProto().getVersionTime().getNanos(), + OffsetDateTime.now().getOffset()) + )); } // [END spanner_create_backup] // [START spanner_cancel_backup_create] static void cancelCreateBackup( - DatabaseAdminClient dbAdminClient, String projectId, String instanceId, - String databaseId, String backupId) { + DatabaseAdminClient dbAdminClient, DatabaseId databaseId, BackupId backupId) { // Set expire time to 14 days from now. - Timestamp expireTime = - Timestamp.newBuilder().setSeconds(TimeUnit.MILLISECONDS.toSeconds(( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14)))).build(); - BackupName backupName = BackupName.of(projectId, instanceId, backupId); - Backup backup = Backup.newBuilder() - .setName(backupName.toString()) - .setDatabase(DatabaseName.of(projectId, instanceId, databaseId).toString()) - .setExpireTime(expireTime).build(); - + Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS)); + + // Create a backup instance. + Backup backup = + dbAdminClient + .newBackupBuilder(backupId) + .setDatabase(databaseId) + .setExpireTime(expireTime) + .build(); + // Start the creation of a backup. + System.out.println("Creating backup [" + backup.getId() + "]..."); + OperationFuture op = backup.create(); try { - // Start the creation of a backup. - System.out.println("Creating backup [" + backupId + "]..."); - OperationFuture op = dbAdminClient.createBackupAsync( - InstanceName.of(projectId, instanceId), backup, backupId); - // Try to cancel the backup operation. - System.out.println("Cancelling create backup operation for [" + backupId + "]..."); - dbAdminClient.getOperationsClient().cancelOperation(op.getName()); - + System.out.println("Cancelling create backup operation for [" + backup.getId() + "]..."); + dbAdminClient.cancelOperation(op.getName()); // Get a polling future for the running operation. This future will regularly poll the server // for the current status of the backup operation. RetryingFuture pollingFuture = op.getPollingFuture(); - // Wait for the operation to finish. // isDone will return true when the operation is complete, regardless of whether it was // successful or not. @@ -1631,11 +1647,11 @@ static void cancelCreateBackup( } if (pollingFuture.get().getErrorCode() == null) { // Backup was created before it could be cancelled. Delete the backup. - dbAdminClient.deleteBackup(backupName); - System.out.println("Backup operation for [" + backupId + backup.delete(); + System.out.println("Backup operation for [" + backup.getId() + "] successfully finished before it could be cancelled"); } else if (pollingFuture.get().getErrorCode().getCode() == StatusCode.Code.CANCELLED) { - System.out.println("Backup operation for [" + backupId + "] successfully cancelled"); + System.out.println("Backup operation for [" + backup.getId() + "] successfully cancelled"); } } catch (ExecutionException e) { throw SpannerExceptionFactory.newSpannerException(e.getCause()); @@ -1647,22 +1663,20 @@ static void cancelCreateBackup( // [START spanner_list_backup_operations] static void listBackupOperations( - DatabaseAdminClient databaseAdminClient, - String projectId, String instanceId, - String databaseId, String backupId) { - InstanceName instanceName = InstanceName.of(projectId, instanceId); - // Get 'CreateBackup' operations for the sample database. + InstanceAdminClient instanceAdminClient, DatabaseId databaseId, BackupId backupId) { + Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance()); + // Get create backup operations for the sample database. + Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert( + TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, + TimeUnit.HOURS), 0); String filter = String.format( - "(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.CreateBackupMetadata) " - + "AND (metadata.database:%s)", - DatabaseName.of(projectId, instanceId, databaseId).toString()); - ListBackupOperationsRequest listBackupOperationsRequest = - ListBackupOperationsRequest.newBuilder() - .setParent(instanceName.toString()).setFilter(filter).build(); - ListBackupOperationsPagedResponse createBackupOperations - = databaseAdminClient.listBackupOperations(listBackupOperationsRequest); + "(metadata.@type:type.googleapis.com/" + + "google.spanner.admin.database.v1.CreateBackupMetadata) " + + "AND (metadata.database:%s)", + databaseId.getName()); + Page createBackupOperations = instance.listBackupOperations( + Options.filter(filter)); System.out.println("Create Backup Operations:"); for (Operation op : createBackupOperations.iterateAll()) { try { @@ -1679,27 +1693,24 @@ static void listBackupOperations( } } // Get copy backup operations for the sample database. - filter = String.format( - "(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.CopyBackupMetadata) " - + "AND (metadata.source_backup:%s)", - BackupName.of(projectId, instanceId, backupId).toString()); - listBackupOperationsRequest = - ListBackupOperationsRequest.newBuilder() - .setParent(instanceName.toString()).setFilter(filter).build(); - ListBackupOperationsPagedResponse copyBackupOperations = - databaseAdminClient.listBackupOperations(listBackupOperationsRequest); + filter = + String.format( + "(metadata.@type:type.googleapis.com/" + + "google.spanner.admin.database.v1.CopyBackupMetadata) " + + "AND (metadata.source_backup:%s)", + backupId.getName()); + Page copyBackupOperations = instance.listBackupOperations(Options.filter(filter)); System.out.println("Copy Backup Operations:"); for (Operation op : copyBackupOperations.iterateAll()) { try { CopyBackupMetadata copyBackupMetadata = - op.getMetadata().unpack(CopyBackupMetadata.class); + op.getMetadata().unpack(CopyBackupMetadata.class); System.out.println( - String.format( - "Copy Backup %s on backup %s pending: %d%% complete", - copyBackupMetadata.getName(), - copyBackupMetadata.getSourceBackup(), - copyBackupMetadata.getProgress().getProgressPercent())); + String.format( + "Copy Backup %s on backup %s pending: %d%% complete", + copyBackupMetadata.getName(), + copyBackupMetadata.getSourceBackup(), + copyBackupMetadata.getProgress().getProgressPercent())); } catch (InvalidProtocolBufferException e) { // The returned operation does not contain CopyBackupMetadata. System.err.println(e.getMessage()); @@ -1710,23 +1721,18 @@ static void listBackupOperations( // [START spanner_list_database_operations] static void listDatabaseOperations( - DatabaseAdminClient dbAdminClient, String projectId, String instanceId) { + InstanceAdminClient instanceAdminClient, + DatabaseAdminClient dbAdminClient, + InstanceId instanceId) { + Instance instance = instanceAdminClient.getInstance(instanceId.getInstance()); // Get optimize restored database operations. - com.google.cloud.Timestamp last24Hours = com.google.cloud.Timestamp.ofTimeSecondsAndNanos( - TimeUnit.SECONDS.convert( - TimeUnit.HOURS.convert(com.google.cloud.Timestamp.now().getSeconds(), TimeUnit.SECONDS) - - 24, - TimeUnit.HOURS), 0); + Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert( + TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24, + TimeUnit.HOURS), 0); String filter = String.format("(metadata.@type:type.googleapis.com/" - + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) AND " - + "(metadata.progress.start_time > \"%s\")", last24Hours); - ListDatabaseOperationsRequest listDatabaseOperationsRequest = - ListDatabaseOperationsRequest.newBuilder() - .setParent(com.google.spanner.admin.instance.v1.InstanceName.of( - projectId, instanceId).toString()).setFilter(filter).build(); - ListDatabaseOperationsPagedResponse pagedResponse - = dbAdminClient.listDatabaseOperations(listDatabaseOperationsRequest); - for (Operation op : pagedResponse.iterateAll()) { + + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) AND " + + "(metadata.progress.start_time > \"%s\")", last24Hours); + for (Operation op : instance.listDatabaseOperations(Options.filter(filter)).iterateAll()) { try { OptimizeRestoredDatabaseMetadata metadata = op.getMetadata().unpack(OptimizeRestoredDatabaseMetadata.class); @@ -1744,92 +1750,74 @@ static void listDatabaseOperations( // [START spanner_list_backups] static void listBackups( - DatabaseAdminClient dbAdminClient, String projectId, - String instanceId, String databaseId, String backupId) { - InstanceName instanceName = InstanceName.of(projectId, instanceId); + InstanceAdminClient instanceAdminClient, DatabaseId databaseId, BackupId backupId) { + Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance()); // List all backups. System.out.println("All backups:"); - for (Backup backup : dbAdminClient.listBackups( - instanceName.toString()).iterateAll()) { + for (Backup backup : instance.listBackups().iterateAll()) { System.out.println(backup); } // List all backups with a specific name. System.out.println( - String.format("All backups with backup name containing \"%s\":", backupId)); - ListBackupsRequest listBackupsRequest = - ListBackupsRequest.newBuilder().setParent(instanceName.toString()) - .setFilter(String.format("name:%s", backupId)).build(); - for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { + String.format("All backups with backup name containing \"%s\":", backupId.getBackup())); + for (Backup backup : instance.listBackups( + Options.filter(String.format("name:%s", backupId.getBackup()))).iterateAll()) { System.out.println(backup); } // List all backups for databases whose name contains a certain text. System.out.println( String.format( - "All backups for databases with a name containing \"%s\":", databaseId)); - listBackupsRequest = - ListBackupsRequest.newBuilder().setParent(instanceName.toString()) - .setFilter(String.format("database:%s", databaseId)).build(); - for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { + "All backups for databases with a name containing \"%s\":", + databaseId.getDatabase())); + for (Backup backup : instance.listBackups( + Options.filter(String.format("database:%s", databaseId.getDatabase()))).iterateAll()) { System.out.println(backup); } // List all backups that expire before a certain time. - com.google.cloud.Timestamp expireTime = com.google.cloud.Timestamp.ofTimeMicroseconds( - TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30), TimeUnit.MILLISECONDS)); - - System.out.println(String.format("All backups that expire before %s:", expireTime)); - listBackupsRequest = - ListBackupsRequest.newBuilder().setParent(instanceName.toString()) - .setFilter(String.format("expire_time < \"%s\"", expireTime)).build(); - - for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { + Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30), TimeUnit.MILLISECONDS)); + System.out.println(String.format("All backups that expire before %s:", expireTime.toString())); + for (Backup backup : + instance.listBackups( + Options.filter(String.format("expire_time < \"%s\"", expireTime.toString()))) + .iterateAll()) { System.out.println(backup); } // List all backups with size greater than a certain number of bytes. - listBackupsRequest = - ListBackupsRequest.newBuilder().setParent(instanceName.toString()) - .setFilter("size_bytes > 100").build(); - System.out.println("All backups with size greater than 100 bytes:"); - for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { + for (Backup backup : instance.listBackups(Options.filter("size_bytes > 100")).iterateAll()) { System.out.println(backup); } // List all backups with a create time after a certain timestamp and that are also ready. - com.google.cloud.Timestamp createTime = com.google.cloud.Timestamp.ofTimeMicroseconds( - TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1), TimeUnit.MILLISECONDS)); - + Timestamp createTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1), TimeUnit.MILLISECONDS)); System.out.println( String.format( "All databases created after %s and that are ready:", createTime.toString())); - listBackupsRequest = - ListBackupsRequest.newBuilder().setParent(instanceName.toString()) - .setFilter(String.format( - "create_time >= \"%s\" AND state:READY", createTime.toString())).build(); - for (Backup backup : dbAdminClient.listBackups(listBackupsRequest).iterateAll()) { + for (Backup backup : + instance + .listBackups(Options.filter( + String.format("create_time >= \"%s\" AND state:READY", createTime.toString()))) + .iterateAll()) { System.out.println(backup); } // List backups using pagination. System.out.println("All backups, listed using pagination:"); - listBackupsRequest = - ListBackupsRequest.newBuilder().setParent(instanceName.toString()).setPageSize(10).build(); + Page page = instance.listBackups(Options.pageSize(10)); while (true) { - ListBackupsPagedResponse response = dbAdminClient.listBackups(listBackupsRequest); - for (Backup backup : response.getPage().iterateAll()) { + for (Backup backup : page.getValues()) { System.out.println(backup); } - String nextPageToken = response.getNextPageToken(); - if (!Strings.isNullOrEmpty(nextPageToken)) { - listBackupsRequest = listBackupsRequest.toBuilder().setPageToken(nextPageToken).build(); - } else { + if (!page.hasNextPage()) { break; } + page = page.getNextPage(); } } // [END spanner_list_backups] @@ -1837,35 +1825,31 @@ static void listBackups( // [START spanner_restore_backup] static void restoreBackup( DatabaseAdminClient dbAdminClient, - String projectId, - String instanceId, - String backupId, - String restoreToDatabaseId) { - BackupName backupName = BackupName.of(projectId, instanceId, backupId); - Backup backup = dbAdminClient.getBackup(backupName); + BackupId backupId, + DatabaseId sourceDatabaseId, + DatabaseId restoreToDatabase) { + Backup backup = dbAdminClient.newBackupBuilder(backupId).build(); // Initiate the request which returns an OperationFuture. System.out.println(String.format( - "Restoring backup [%s] to database [%s]...", backup.getName(), restoreToDatabaseId)); + "Restoring backup [%s] to database [%s]...", + backup.getId().toString(), + restoreToDatabase.toString())); try { - RestoreDatabaseRequest request = - RestoreDatabaseRequest.newBuilder() - .setParent(InstanceName.of(projectId, instanceId).toString()) - .setDatabaseId(restoreToDatabaseId) - .setBackup(backupName.toString()).build(); - OperationFuture op = - dbAdminClient.restoreDatabaseAsync(request); + OperationFuture op = backup.restore(restoreToDatabase); // Wait until the database has been restored. - com.google.spanner.admin.database.v1.Database db = op.get(); - // Get the restore info. - RestoreInfo restoreInfo = db.getRestoreInfo(); - BackupInfo backupInfo = restoreInfo.getBackupInfo(); - + Database db = op.get(); + // Refresh database metadata and get the restore info. + RestoreInfo restore = db.reload().getRestoreInfo(); + Timestamp versionTime = Timestamp.fromProto(restore + .getProto() + .getBackupInfo() + .getVersionTime()); System.out.println( "Restored database [" - + db.getName() + + restore.getSourceDatabase().getName() + "] from [" - + restoreInfo.getBackupInfo().getBackup() - + "] with version time [" + backupInfo.getVersionTime() + "]"); + + restore.getBackup().getName() + + "] with version time [" + versionTime + "]"); } catch (ExecutionException e) { throw SpannerExceptionFactory.newSpannerException(e.getCause()); } catch (InterruptedException e) { @@ -1875,59 +1859,49 @@ static void restoreBackup( // [END spanner_restore_backup] // [START spanner_update_backup] - static void updateBackup(DatabaseAdminClient dbAdminClient, String projectId, - String instanceId, String backupId) { - BackupName backupName = BackupName.of(projectId, instanceId, backupId); - + static void updateBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) { // Get current backup metadata. - Backup backup = dbAdminClient.getBackup(backupName); + Backup backup = dbAdminClient.newBackupBuilder(backupId).build().reload(); // Add 30 days to the expire time. // Expire time must be within 366 days of the create time of the backup. - Timestamp currentExpireTime = backup.getExpireTime(); - com.google.cloud.Timestamp newExpireTime = - com.google.cloud.Timestamp.ofTimeMicroseconds( - TimeUnit.SECONDS.toMicros(currentExpireTime.getSeconds()) - + TimeUnit.NANOSECONDS.toMicros(currentExpireTime.getNanos()) + Timestamp expireTime = + Timestamp.ofTimeMicroseconds( + TimeUnit.SECONDS.toMicros(backup.getExpireTime().getSeconds()) + + TimeUnit.NANOSECONDS.toMicros(backup.getExpireTime().getNanos()) + TimeUnit.DAYS.toMicros(30L)); - // New Expire Time must be less than Max Expire Time - newExpireTime = - newExpireTime.compareTo(com.google.cloud.Timestamp.fromProto(backup.getMaxExpireTime())) - < 0 ? newExpireTime : com.google.cloud.Timestamp.fromProto(backup.getMaxExpireTime()); + expireTime = expireTime.compareTo(backup.getMaxExpireTime()) + < 0 ? expireTime : backup.getMaxExpireTime(); + int timeDiff = expireTime.compareTo(backup.getExpireTime()); + Timestamp newExpireTime = (timeDiff < 0) ? expireTime : backup.getExpireTime(); System.out.println(String.format( "Updating expire time of backup [%s] to %s...", backupId.toString(), - java.time.OffsetDateTime.ofInstant( - Instant.ofEpochSecond(newExpireTime.getSeconds(), - newExpireTime.getNanos()), ZoneId.systemDefault()))); + LocalDateTime.ofEpochSecond( + expireTime.getSeconds(), + expireTime.getNanos(), + OffsetDateTime.now().getOffset()).toString())); // Update expire time. - backup = backup.toBuilder().setExpireTime(newExpireTime.toProto()).build(); - dbAdminClient.updateBackup(backup, - FieldMask.newBuilder().addAllPaths(Lists.newArrayList("expire_time")).build()); + backup = backup.toBuilder().setExpireTime(expireTime).build(); + backup.updateExpireTime(); System.out.println("Updated backup [" + backupId + "]"); } // [END spanner_update_backup] // [START spanner_delete_backup] - static void deleteBackup(DatabaseAdminClient dbAdminClient, - String project, String instance, String backupId) { - BackupName backupName = BackupName.of(project, instance, backupId); - + static void deleteBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) { + Backup backup = dbAdminClient.newBackupBuilder(backupId).build(); // Delete the backup. System.out.println("Deleting backup [" + backupId + "]..."); - dbAdminClient.deleteBackup(backupName); + backup.delete(); // Verify that the backup is deleted. - try { - dbAdminClient.getBackup(backupName); - } catch (NotFoundException e) { - if (e.getStatusCode().getCode() == Code.NOT_FOUND) { - System.out.println("Deleted backup [" + backupId + "]"); - } else { - System.out.println("Delete backup [" + backupId + "] failed"); - throw new RuntimeException("Delete backup [" + backupId + "] failed", e); - } + if (backup.exists()) { + System.out.println("Delete backup [" + backupId + "] failed"); + throw new RuntimeException("Delete backup [" + backupId + "] failed"); + } else { + System.out.println("Deleted backup [" + backupId + "]"); } } // [END spanner_delete_backup] @@ -1935,13 +1909,13 @@ static void deleteBackup(DatabaseAdminClient dbAdminClient, static void run( DatabaseClient dbClient, DatabaseAdminClient dbAdminClient, + InstanceAdminClient instanceAdminClient, String command, DatabaseId database, - String backupId) { + BackupId backup) { switch (command) { case "createdatabase": - createDatabase(dbAdminClient, InstanceName.of(database.getInstanceId().getProject(), - database.getInstanceId().getInstance()), database.getDatabase()); + createDatabase(dbAdminClient, database); break; case "write": writeExampleData(dbClient); @@ -1956,8 +1930,7 @@ static void run( read(dbClient); break; case "addmarketingbudget": - addMarketingBudget(dbAdminClient, DatabaseName.of(database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase())); + addMarketingBudget(dbAdminClient, database); break; case "update": update(dbClient); @@ -1969,8 +1942,7 @@ static void run( queryMarketingBudget(dbClient); break; case "addindex": - addIndex(dbAdminClient, DatabaseName.of(database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase())); + addIndex(dbAdminClient, database); break; case "readindex": readUsingIndex(dbClient); @@ -1979,8 +1951,7 @@ static void run( queryUsingIndex(dbClient); break; case "addstoringindex": - addStoringIndex(dbAdminClient, DatabaseName.of(database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase())); + addStoringIndex(dbAdminClient, database); break; case "readstoringindex": readStoringIndex(dbClient); @@ -1992,8 +1963,7 @@ static void run( readStaleData(dbClient); break; case "addcommittimestamp": - addCommitTimestamp(dbAdminClient, DatabaseName.of(database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase())); + addCommitTimestamp(dbAdminClient, database); break; case "updatewithtimestamp": updateWithTimestamp(dbClient); @@ -2002,9 +1972,7 @@ static void run( queryMarketingBudgetWithTimestamp(dbClient); break; case "createtablewithtimestamp": - createTableWithTimestamp(dbAdminClient, - DatabaseName.of(database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase())); + createTableWithTimestamp(dbAdminClient, database); break; case "writewithtimestamp": writeExampleDataWithTimestamp(dbClient); @@ -2067,9 +2035,7 @@ static void run( updateUsingBatchDml(dbClient); break; case "createtablewithdatatypes": - createTableWithDatatypes(dbAdminClient, - DatabaseName.of(database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase())); + createTableWithDatatypes(dbAdminClient, database); break; case "writedatatypesdata": writeDatatypesData(dbClient); @@ -2108,41 +2074,35 @@ static void run( queryWithQueryOptions(dbClient); break; case "createbackup": - createBackup(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase(), - backupId, getVersionTime(dbClient)); + createBackup(dbAdminClient, database, backup, getVersionTime(dbClient)); break; case "cancelcreatebackup": cancelCreateBackup( dbAdminClient, - database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase(), - backupId + "_cancel"); + database, + BackupId.of(backup.getInstanceId(), backup.getBackup() + "_cancel")); break; case "listbackupoperations": - listBackupOperations(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase(), backupId); + listBackupOperations(instanceAdminClient, database, backup); break; case "listdatabaseoperations": - listDatabaseOperations(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance()); + listDatabaseOperations(instanceAdminClient, dbAdminClient, database.getInstanceId()); break; case "listbackups": - listBackups(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), database.getDatabase(), backupId); + listBackups(instanceAdminClient, database, backup); break; case "restorebackup": restoreBackup( - dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), backupId, database.getDatabase()); + dbAdminClient, + backup, + database, + DatabaseId.of(database.getInstanceId(), createRestoredSampleDbId(database))); break; case "updatebackup": - updateBackup(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), backupId); + updateBackup(dbAdminClient, backup); break; case "deletebackup": - deleteBackup(dbAdminClient, database.getInstanceId().getProject(), - database.getInstanceId().getInstance(), backupId); + deleteBackup(dbAdminClient, backup); break; default: printUsageAndExit(); @@ -2151,13 +2111,13 @@ static void run( static Timestamp getVersionTime(DatabaseClient dbClient) { // Generates a version time for the backup - com.google.cloud.Timestamp versionTime; + Timestamp versionTime; try (ResultSet resultSet = dbClient.singleUse() .executeQuery(Statement.of("SELECT CURRENT_TIMESTAMP()"))) { resultSet.next(); versionTime = resultSet.getTimestamp(0); } - return versionTime.toProto(); + return versionTime; } static void printUsageAndExit() { @@ -2225,16 +2185,15 @@ static void printUsageAndExit() { System.exit(1); } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { if (args.length != 3 && args.length != 4) { printUsageAndExit(); } // [START init_client] SpannerOptions options = SpannerOptions.newBuilder().build(); Spanner spanner = options.getService(); - DatabaseAdminClient dbAdminClient = null; try { - final String command = args[0]; + String command = args[0]; DatabaseId db = DatabaseId.of(options.getProjectId(), args[1], args[2]); // [END init_client] // This will return the default project id based on the environment. @@ -2247,26 +2206,25 @@ public static void main(String[] args) { printUsageAndExit(); } // Generate a backup id for the sample database. - String backupId = null; + String backupName = + String.format( + "%s_%02d", + db.getDatabase(), LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR)); + BackupId backup = BackupId.of(db.getInstanceId(), backupName); if (args.length == 4) { - backupId = args[3]; + backupName = args[3]; } // [START init_client] DatabaseClient dbClient = spanner.getDatabaseClient(db); - dbAdminClient = spanner.createDatabaseAdminClient(); - + DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); + InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); // Use client here... // [END init_client] - run(dbClient, dbAdminClient, command, db, backupId); + run(dbClient, dbAdminClient, instanceAdminClient, command, db, backup); // [START init_client] } finally { - if (dbAdminClient != null) { - if (!dbAdminClient.isShutdown() || !dbAdminClient.isTerminated()) { - dbAdminClient.close(); - } - } spanner.close(); } // [END init_client] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateDatabaseSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateDatabaseSample.java similarity index 62% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateDatabaseSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateDatabaseSample.java index 4e4f76d700..5fcd9ab5ed 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateDatabaseSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateDatabaseSample.java @@ -14,21 +14,18 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_update_database] - import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.DatabaseInfo.DatabaseField; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.common.collect.Lists; -import com.google.protobuf.FieldMask; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.DatabaseName; import com.google.spanner.admin.database.v1.UpdateDatabaseMetadata; -import com.google.spanner.admin.database.v1.UpdateDatabaseRequest; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -40,31 +37,22 @@ static void updateDatabase() { final String projectId = "my-project"; final String instanceId = "my-instance"; final String databaseId = "my-database"; - updateDatabase(projectId, instanceId, databaseId); } - static void updateDatabase( - String projectId, String instanceId, String databaseId) { + static void updateDatabase(String projectId, String instanceId, String databaseId) { try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - final Database database = - Database.newBuilder() - .setName(DatabaseName.of(projectId, instanceId, databaseId).toString()) - .setEnableDropProtection(true).build(); - final UpdateDatabaseRequest updateDatabaseRequest = - UpdateDatabaseRequest.newBuilder() - .setDatabase(database) - .setUpdateMask( - FieldMask.newBuilder().addAllPaths( - Lists.newArrayList("enable_drop_protection")).build()) - .build(); + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + + DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); + Database databaseToUpdate = + databaseAdminClient.newDatabaseBuilder(dbId).enableDropProtection().build(); OperationFuture operation = - databaseAdminClient.updateDatabaseAsync(updateDatabaseRequest); - System.out.printf("Waiting for update operation for %s to complete...\n", databaseId); + databaseAdminClient.updateDatabase(databaseToUpdate, DatabaseField.DROP_PROTECTION); + System.out.printf("Waiting for update operation for %s to complete...\n", dbId); Database updatedDb = operation.get(5, TimeUnit.MINUTES); - System.out.printf("Updated database %s.\n", updatedDb.getName()); + System.out.printf("Updated database %s.\n", updatedDb.getId().getName()); } catch (ExecutionException | TimeoutException e) { // If the operation failed during execution, expose the cause. throw SpannerExceptionFactory.asSpannerException(e.getCause()); diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateDatabaseWithDefaultLeaderSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateDatabaseWithDefaultLeaderSample.java similarity index 76% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateDatabaseWithDefaultLeaderSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateDatabaseWithDefaultLeaderSample.java index 26c252ac1e..8971399093 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateDatabaseWithDefaultLeaderSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateDatabaseWithDefaultLeaderSample.java @@ -14,16 +14,17 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; //[START spanner_update_database_with_default_leader] +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; 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.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.Collections; import java.util.concurrent.ExecutionException; @@ -40,20 +41,26 @@ static void updateDatabaseWithDefaultLeader() { static void updateDatabaseWithDefaultLeader( String projectId, String instanceId, String databaseId, String defaultLeader) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - databaseAdminClient - .updateDatabaseDdlAsync( - DatabaseName.of(projectId, instanceId, databaseId), + try (Spanner spanner = SpannerOptions + .newBuilder() + .setProjectId(projectId) + .build() + .getService()) { + final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient(); + final OperationFuture operation = databaseAdminClient + .updateDatabaseDdl( + instanceId, + databaseId, Collections.singletonList( String.format( "ALTER DATABASE `%s` SET OPTIONS (default_leader = '%s')", databaseId, defaultLeader ) - ) - ).get(); + ), + null + ); + operation.get(); System.out.println("Updated default leader to " + defaultLeader); } catch (ExecutionException e) { // If the operation failed during execution, expose the cause. diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateInstanceConfigSample.java similarity index 52% rename from samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateInstanceConfigSample.java rename to samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateInstanceConfigSample.java index e74d8071c2..8110e3782c 100644 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/UpdateInstanceConfigSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/UpdateInstanceConfigSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Google LLC + * 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. @@ -14,24 +14,24 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; // [START spanner_update_instance_config] - +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceConfig; +import com.google.cloud.spanner.InstanceConfigId; +import com.google.cloud.spanner.InstanceConfigInfo; +import com.google.cloud.spanner.InstanceConfigInfo.InstanceConfigField; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; import com.google.common.collect.ImmutableList; -import com.google.protobuf.FieldMask; -import com.google.spanner.admin.instance.v1.InstanceConfig; -import com.google.spanner.admin.instance.v1.InstanceConfigName; -import com.google.spanner.admin.instance.v1.UpdateInstanceConfigRequest; +import com.google.spanner.admin.instance.v1.UpdateInstanceConfigMetadata; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; class UpdateInstanceConfigSample { - static void updateInstanceConfig() { // TODO(developer): Replace these variables before running the sample. String projectId = "my-project"; @@ -41,42 +41,27 @@ static void updateInstanceConfig() { static void updateInstanceConfig(String projectId, String instanceConfigId) { try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - final InstanceConfigName instanceConfigName = - InstanceConfigName.of(projectId, instanceConfigId); - final InstanceConfig instanceConfig = - InstanceConfig.newBuilder() - .setName(instanceConfigName.toString()) + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + InstanceConfigInfo instanceConfigInfo = + InstanceConfig.newBuilder(InstanceConfigId.of(projectId, instanceConfigId)) .setDisplayName("updated custom instance config") - .putLabels("updated", "true").build(); - /** - * The field mask must always be specified; this prevents any future - * fields in [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig] - * from being erased accidentally by clients that do not know about them. - */ - final UpdateInstanceConfigRequest updateInstanceConfigRequest = - UpdateInstanceConfigRequest.newBuilder() - .setInstanceConfig(instanceConfig) - .setUpdateMask( - FieldMask.newBuilder().addAllPaths(ImmutableList.of("display_name", "labels")) - .build()).build(); + .addLabel("updated", "true") + .build(); + final OperationFuture operation = + instanceAdminClient.updateInstanceConfig( + instanceConfigInfo, + ImmutableList.of(InstanceConfigField.DISPLAY_NAME, InstanceConfigField.LABELS)); try { - System.out.printf("Waiting for update operation on %s to complete...\n", - instanceConfigName); - InstanceConfig instanceConfigResult = - instanceAdminClient.updateInstanceConfigAsync( - updateInstanceConfigRequest).get(5, TimeUnit.MINUTES); + System.out.printf("Waiting for update operation on %s to complete...\n", instanceConfigId); + InstanceConfig instanceConfig = operation.get(5, TimeUnit.MINUTES); System.out.printf( "Updated instance configuration %s with new display name %s\n", - instanceConfigResult.getName(), instanceConfig.getDisplayName()); + instanceConfig.getId(), instanceConfig.getDisplayName()); } catch (ExecutionException | TimeoutException e) { System.out.printf( "Error: Updating instance config %s failed with error message %s\n", - instanceConfig.getName(), e.getMessage()); + instanceConfigInfo.getId(), e.getMessage()); e.printStackTrace(); } catch (InterruptedException e) { System.out.println( diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddAndDropDatabaseRole.java b/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddAndDropDatabaseRole.java deleted file mode 100644 index 69a154e882..0000000000 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/AddAndDropDatabaseRole.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.Spanner; -import com.google.cloud.spanner.SpannerOptions; -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.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class AddAndDropDatabaseRole { - - static void addAndDropDatabaseRole() { - // 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) { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - 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] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CopyBackupSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/generated/CopyBackupSample.java deleted file mode 100644 index 245abd9429..0000000000 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CopyBackupSample.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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_copy_backup] - -import com.google.cloud.Timestamp; -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.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.spanner.admin.database.v1.Backup; -import com.google.spanner.admin.database.v1.BackupName; -import com.google.spanner.admin.database.v1.InstanceName; -import java.time.Instant; -import java.time.OffsetDateTime; -import java.time.ZoneId; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -public class CopyBackupSample { - - static void copyBackup() { - // TODO(developer): Replace these variables before running the sample. - String projectId = "my-project"; - String instanceId = "my-instance"; - String sourceBackupId = "my-backup"; - String destinationBackupId = "my-destination-backup"; - - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - copyBackup(databaseAdminClient, projectId, instanceId, sourceBackupId, destinationBackupId); - } - } - - static void copyBackup( - DatabaseAdminClient databaseAdminClient, - String projectId, - String instanceId, - String sourceBackupId, - String destinationBackupId) { - - Timestamp expireTime = - Timestamp.ofTimeMicroseconds( - TimeUnit.MICROSECONDS.convert( - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), - TimeUnit.MILLISECONDS)); - - // Initiate the request which returns an OperationFuture. - System.out.println("Copying backup [" + destinationBackupId + "]..."); - Backup destinationBackup; - try { - // Creates a copy of an existing backup. - // Wait for the backup operation to complete. - destinationBackup = databaseAdminClient.copyBackupAsync( - InstanceName.of(projectId, instanceId), destinationBackupId, - BackupName.of(projectId, instanceId, sourceBackupId), expireTime.toProto()).get(); - System.out.println("Copied backup [" + destinationBackup.getName() + "]"); - } catch (ExecutionException e) { - throw (SpannerException) e.getCause(); - } catch (InterruptedException e) { - throw SpannerExceptionFactory.propagateInterrupt(e); - } - // Load the metadata of the new backup from the server. - destinationBackup = databaseAdminClient.getBackup(destinationBackup.getName()); - System.out.println( - String.format( - "Backup %s of size %d bytes was copied at %s for version of database at %s", - destinationBackup.getName(), - destinationBackup.getSizeBytes(), - OffsetDateTime.ofInstant( - Instant.ofEpochSecond(destinationBackup.getCreateTime().getSeconds(), - destinationBackup.getCreateTime().getNanos()), - ZoneId.systemDefault()), - OffsetDateTime.ofInstant( - Instant.ofEpochSecond(destinationBackup.getVersionTime().getSeconds(), - destinationBackup.getVersionTime().getNanos()), - ZoneId.systemDefault()))); - } -} -// [END spanner_copy_backup] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceConfigSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceConfigSample.java deleted file mode 100644 index 8671c6eda3..0000000000 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceConfigSample.java +++ /dev/null @@ -1,94 +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.example.spanner.admin.generated; - -// [START spanner_create_instance_config] - -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; -import com.google.spanner.admin.instance.v1.CreateInstanceConfigRequest; -import com.google.spanner.admin.instance.v1.InstanceConfig; -import com.google.spanner.admin.instance.v1.InstanceConfigName; -import com.google.spanner.admin.instance.v1.ProjectName; -import com.google.spanner.admin.instance.v1.ReplicaInfo; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -class CreateInstanceConfigSample { - - static void createInstanceConfig() { - // TODO(developer): Replace these variables before running the sample. - String projectId = "my-project"; - String baseInstanceConfigId = "nam11"; - String instanceConfigId = "custom-instance-config4"; - - createInstanceConfig(projectId, baseInstanceConfigId, instanceConfigId); - } - - static void createInstanceConfig( - String projectId, String baseInstanceConfigId, String instanceConfigId) { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - final InstanceConfigName baseInstanceConfigName = InstanceConfigName.of(projectId, - baseInstanceConfigId); - final InstanceConfig baseConfig = - instanceAdminClient.getInstanceConfig(baseInstanceConfigName.toString()); - final InstanceConfigName instanceConfigName = InstanceConfigName.of(projectId, - instanceConfigId); - /** - * The replicas for the custom instance configuration must include all the replicas of the - * base configuration, in addition to at least one from the list of optional replicas of the - * base configuration. - */ - final List replicas = - Stream.concat(baseConfig.getReplicasList().stream(), - baseConfig.getOptionalReplicasList().stream().limit(1)).collect(Collectors.toList()); - final InstanceConfig instanceConfig = - InstanceConfig.newBuilder().setName(instanceConfigName.toString()) - .setBaseConfig(baseInstanceConfigName.toString()) - .setDisplayName("Instance Configuration").addAllReplicas(replicas).build(); - final CreateInstanceConfigRequest createInstanceConfigRequest = - CreateInstanceConfigRequest.newBuilder().setParent(ProjectName.of(projectId).toString()) - .setInstanceConfigId(instanceConfigId).setInstanceConfig(instanceConfig).build(); - try { - System.out.printf("Waiting for create operation for %s to complete...\n", - instanceConfigName); - InstanceConfig instanceConfigResult = - instanceAdminClient.createInstanceConfigAsync( - createInstanceConfigRequest).get(5, TimeUnit.MINUTES); - System.out.printf("Created instance configuration %s\n", instanceConfigResult.getName()); - } catch (ExecutionException | TimeoutException e) { - System.out.printf( - "Error: Creating instance configuration %s failed with error message %s\n", - instanceConfig.getName(), e.getMessage()); - } catch (InterruptedException e) { - System.out.println( - "Error: Waiting for createInstanceConfig operation to finish was interrupted"); - } - } - } -} -// [END spanner_create_instance_config] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceWithAutoscalingConfigExample.java b/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceWithAutoscalingConfigExample.java deleted file mode 100644 index 3faaced75b..0000000000 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceWithAutoscalingConfigExample.java +++ /dev/null @@ -1,93 +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.example.spanner.admin.generated; - -// [START spanner_create_instance_with_autoscaling_config] - -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; -import com.google.spanner.admin.instance.v1.AutoscalingConfig; -import com.google.spanner.admin.instance.v1.CreateInstanceRequest; -import com.google.spanner.admin.instance.v1.Instance; -import com.google.spanner.admin.instance.v1.InstanceConfigName; -import com.google.spanner.admin.instance.v1.ProjectName; -import java.util.concurrent.ExecutionException; - -class CreateInstanceWithAutoscalingConfigExample { - - static void createInstance() { - // TODO(developer): Replace these variables before running the sample. - String projectId = "my-project"; - String instanceId = "my-instance"; - createInstance(projectId, instanceId); - } - - static void createInstance(String projectId, String instanceId) { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - // Set Instance configuration. - String configId = "regional-us-central1"; - String displayName = "Descriptive name"; - - // Create an autoscaling config. - // When autoscaling_config is enabled, node_count and processing_units fields - // need not be specified. - AutoscalingConfig autoscalingConfig = - AutoscalingConfig.newBuilder() - .setAutoscalingLimits( - AutoscalingConfig.AutoscalingLimits.newBuilder().setMinNodes(1).setMaxNodes(2)) - .setAutoscalingTargets( - AutoscalingConfig.AutoscalingTargets.newBuilder() - .setHighPriorityCpuUtilizationPercent(65) - .setStorageUtilizationPercent(95)) - .build(); - Instance instance = - Instance.newBuilder() - .setAutoscalingConfig(autoscalingConfig) - .setDisplayName(displayName) - .setConfig( - InstanceConfigName.of(projectId, configId).toString()) - .build(); - - // Creates a new instance - System.out.printf("Creating instance %s.%n", instanceId); - try { - // Wait for the createInstance operation to finish. - Instance instanceResult = instanceAdminClient.createInstanceAsync( - CreateInstanceRequest.newBuilder() - .setParent(ProjectName.of(projectId).toString()) - .setInstanceId(instanceId) - .setInstance(instance) - .build()).get(); - System.out.printf("Autoscaler instance %s was successfully created%n", - instanceResult.getName()); - } catch (ExecutionException e) { - System.out.printf( - "Error: Creating instance %s failed with error message %s%n", - instance.getName(), e.getMessage()); - } catch (InterruptedException e) { - System.out.println("Error: Waiting for createInstance operation to finish was interrupted"); - } - } - } -} -// [END spanner_create_instance_with_autoscaling_config] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceWithProcessingUnitsExample.java b/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceWithProcessingUnitsExample.java deleted file mode 100644 index 2f6b6d9887..0000000000 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateInstanceWithProcessingUnitsExample.java +++ /dev/null @@ -1,80 +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.example.spanner.admin.generated; - -//[START spanner_create_instance_with_processing_units] - -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; -import com.google.spanner.admin.instance.v1.CreateInstanceRequest; -import com.google.spanner.admin.instance.v1.Instance; -import com.google.spanner.admin.instance.v1.InstanceConfigName; -import com.google.spanner.admin.instance.v1.ProjectName; - -class CreateInstanceWithProcessingUnitsExample { - - static void createInstance() { - // TODO(developer): Replace these variables before running the sample. - String projectId = "my-project"; - String instanceId = "my-instance"; - createInstance(projectId, instanceId); - } - - static void createInstance(String projectId, String instanceId) { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - - // Set Instance configuration. - String configId = "regional-us-central1"; - // This will create an instance with the processing power of 0.2 nodes. - int processingUnits = 500; - String displayName = "Descriptive name"; - - try { - // Creates a new instance - System.out.printf("Creating instance %s.%n", instanceId); - Instance instance = - Instance.newBuilder() - .setDisplayName(displayName) - .setProcessingUnits(processingUnits) - .setConfig( - InstanceConfigName.of(projectId, configId).toString()) - .build(); - // Wait for the createInstance operation to finish. - System.out.printf("Waiting for operation on %s to complete...%n", instanceId); - Instance createdInstance = instanceAdminClient.createInstanceAsync( - CreateInstanceRequest.newBuilder() - .setParent(ProjectName.of(projectId).toString()) - .setInstanceId(instanceId) - .setInstance(instance) - .build()).get(); - - System.out.printf("Created instance %s.%n", createdInstance.getName()); - System.out.printf("Instance %s has %d processing units.%n", createdInstance.getName(), - createdInstance.getProcessingUnits()); - } catch (Exception e) { - System.out.printf("Error: %s.%n", e.getMessage()); - } - } - } -} -//[END spanner_create_instance_with_processing_units] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateTableWithForeignKeyDeleteCascadeSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateTableWithForeignKeyDeleteCascadeSample.java deleted file mode 100644 index 84d09792c1..0000000000 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/CreateTableWithForeignKeyDeleteCascadeSample.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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_create_table_with_foreign_key_delete_cascade] - -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.DatabaseName; - -class CreateTableWithForeignKeyDeleteCascadeSample { - - static void createForeignKeyDeleteCascadeConstraint() { - // TODO(developer): Replace these variables before running the sample. - String projectId = "my-project"; - String instanceId = "my-instance"; - String databaseId = "my-database"; - - createForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId); - } - - static void createForeignKeyDeleteCascadeConstraint( - String projectId, String instanceId, String databaseId) { - try (Spanner spanner = - SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); - DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { - databaseAdminClient.updateDatabaseDdlAsync( - DatabaseName.of(projectId, instanceId, databaseId), - ImmutableList.of( - "CREATE TABLE Customers (\n" - + " CustomerId INT64 NOT NULL,\n" - + " CustomerName STRING(62) NOT NULL,\n" - + " ) PRIMARY KEY (CustomerId)", - "CREATE TABLE ShoppingCarts (\n" - + " CartId INT64 NOT NULL,\n" - + " CustomerId INT64 NOT NULL,\n" - + " CustomerName STRING(62) NOT NULL,\n" - + " CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId)\n" - + " REFERENCES Customers (CustomerId) ON DELETE CASCADE\n" - + " ) PRIMARY KEY (CartId)\n")); - - System.out.printf( - String.format( - "Created Customers and ShoppingCarts table with FKShoppingCartsCustomerId\n" - + "foreign key constraint on database %s on instance %s\n", - databaseId, instanceId)); - } - } -} -// [END spanner_create_table_with_foreign_key_delete_cascade] diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListInstanceConfigOperationsSample.java b/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListInstanceConfigOperationsSample.java deleted file mode 100644 index cbfd1908d4..0000000000 --- a/samples/snippets/src/main/java/com/example/spanner/admin/generated/ListInstanceConfigOperationsSample.java +++ /dev/null @@ -1,73 +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.example.spanner.admin.generated; - -// [START spanner_list_instance_config_operations] - -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; -import com.google.longrunning.Operation; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.spanner.admin.instance.v1.CreateInstanceConfigMetadata; -import com.google.spanner.admin.instance.v1.ListInstanceConfigOperationsRequest; -import com.google.spanner.admin.instance.v1.ProjectName; - -public class ListInstanceConfigOperationsSample { - - static void listInstanceConfigOperations() { - // TODO(developer): Replace these variables before running the sample. - String projectId = "my-project"; - listInstanceConfigOperations(projectId); - } - - static void listInstanceConfigOperations(String projectId) { - try (Spanner spanner = - SpannerOptions.newBuilder() - .setProjectId(projectId) - .build() - .getService(); - InstanceAdminClient instanceAdminClient = spanner.createInstanceAdminClient()) { - final ProjectName projectName = ProjectName.of(projectId); - System.out.printf( - "Getting list of instance config operations for project %s...\n", - projectId); - final ListInstanceConfigOperationsRequest request = - ListInstanceConfigOperationsRequest.newBuilder() - .setParent(projectName.toString()) - .setFilter("(metadata.@type=type.googleapis.com/" - + "google.spanner.admin.instance.v1.CreateInstanceConfigMetadata)").build(); - final Iterable instanceConfigOperations = - instanceAdminClient.listInstanceConfigOperations(request).iterateAll(); - for (Operation operation : instanceConfigOperations) { - CreateInstanceConfigMetadata metadata = - operation.getMetadata().unpack(CreateInstanceConfigMetadata.class); - System.out.printf( - "Create instance config operation for %s is %d%% completed.\n", - metadata.getInstanceConfig().getName(), metadata.getProgress().getProgressPercent()); - } - System.out.printf( - "Obtained list of instance config operations for project %s...\n", - projectName); - } catch (InvalidProtocolBufferException e) { - System.out.printf( - "Error: Listing instance config operations failed with error message %s\n", - e.getMessage()); - } - } -} -// [END spanner_list_instance_config_operations] diff --git a/samples/snippets/src/test/java/com/example/spanner/AlterTableWithForeignKeyDeleteCascadeSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/AlterTableWithForeignKeyDeleteCascadeSampleIT.java index f719424758..a22b5ab375 100644 --- a/samples/snippets/src/test/java/com/example/spanner/AlterTableWithForeignKeyDeleteCascadeSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/AlterTableWithForeignKeyDeleteCascadeSampleIT.java @@ -18,22 +18,24 @@ import static org.junit.Assert.assertTrue; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.InstanceName; import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class AlterTableWithForeignKeyDeleteCascadeSampleIT extends SampleTestBase { +public class AlterTableWithForeignKeyDeleteCascadeSampleIT extends SampleTestBaseV2 { @Test public void testAlterTableWithForeignKeyDeleteCascade() throws Exception { // Creates database final String databaseId = idGenerator.generateDatabaseId(); - databaseAdminClient - .createDatabase( - instanceId, - databaseId, - Arrays.asList( + final CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .setParent(InstanceName.of(projectId, instanceId).toString()) + .addAllExtraStatements(Arrays.asList( "CREATE TABLE Customers (\n" + " CustomerId INT64 NOT NULL,\n" + " CustomerName STRING(62) NOT NULL,\n" @@ -45,15 +47,15 @@ public void testAlterTableWithForeignKeyDeleteCascade() throws Exception { + " CONSTRAINT FKShoppingCartsCustomerId" + " FOREIGN KEY (CustomerId)\n" + " REFERENCES Customers (CustomerId)\n" - + " ) PRIMARY KEY (CartId)\n")) - .get(5, TimeUnit.MINUTES); + + " ) PRIMARY KEY (CartId)\n")).build(); + databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample( () -> AlterTableWithForeignKeyDeleteCascadeSample.alterForeignKeyDeleteCascadeConstraint( - databaseAdminClient, instanceId, databaseId)); + projectId, instanceId, databaseId)); assertTrue( "Expected to have created database " diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CopyBackupIT.java b/samples/snippets/src/test/java/com/example/spanner/CopyBackupIT.java similarity index 98% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/CopyBackupIT.java rename to samples/snippets/src/test/java/com/example/spanner/CopyBackupIT.java index 1d51042888..29854011e1 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CopyBackupIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/CopyBackupIT.java @@ -14,11 +14,10 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner; import static com.google.common.truth.Truth.assertThat; -import com.example.spanner.SampleRunner; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; diff --git a/samples/snippets/src/test/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSampleIT.java index d56d4b14f8..fff67b38b8 100644 --- a/samples/snippets/src/test/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSampleIT.java @@ -1,11 +1,11 @@ /* - * Copyright 2021 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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,33 +18,34 @@ import static org.junit.Assert.assertTrue; -import com.google.cloud.spanner.InstanceConfig; -import com.google.cloud.spanner.InstanceConfigId; +import com.google.spanner.admin.instance.v1.InstanceConfig; +import com.google.spanner.admin.instance.v1.InstanceName; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; -public class CreateDatabaseWithDefaultLeaderSampleIT extends SampleTestBase { +@RunWith(JUnit4.class) +public class CreateDatabaseWithDefaultLeaderSampleIT extends SampleTestBaseV2 { @Test public void testCreateDatabaseWithDefaultLeader() throws Exception { final String databaseId = idGenerator.generateDatabaseId(); // Finds possible default leader - final InstanceConfigId instanceConfigId = instanceAdminClient - .getInstance(multiRegionalInstanceId) - .getInstanceConfigId(); - final InstanceConfig config = instanceAdminClient - .getInstanceConfig(instanceConfigId.getInstanceConfig()); + + final String instanceConfigId = instanceAdminClient.getInstance( + InstanceName.of(projectId, multiRegionalInstanceId)).getConfig(); + final InstanceConfig config = instanceAdminClient.getInstanceConfig(instanceConfigId); assertTrue( "Expected instance config " + instanceConfigId + " to have at least one leader option", - config.getLeaderOptions().size() > 0 + config.getLeaderOptionsCount() > 0 ); - final String defaultLeader = config.getLeaderOptions().get(0); + final String defaultLeader = config.getLeaderOptions(0); // Runs sample final String out = SampleRunner.runSample(() -> CreateDatabaseWithDefaultLeaderSample.createDatabaseWithDefaultLeader( - projectId, - multiRegionalInstanceId, + getInstanceName(projectId, multiRegionalInstanceId), databaseId, defaultLeader ) diff --git a/samples/snippets/src/test/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSampleIT.java index 0e77ffc9a2..98832f1f51 100644 --- a/samples/snippets/src/test/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSampleIT.java @@ -23,10 +23,11 @@ import org.junit.runners.JUnit4; /** - * Integration tests for {@link CreateDatabaseWithVersionRetentionPeriodSample} + * Integration tests for + * {@link com.example.spanner.admin.archived.CreateDatabaseWithVersionRetentionPeriodSample} */ @RunWith(JUnit4.class) -public class CreateDatabaseWithVersionRetentionPeriodSampleIT extends SampleTestBase { +public class CreateDatabaseWithVersionRetentionPeriodSampleIT extends SampleTestBaseV2 { @Test public void createsDatabaseWithVersionRetentionPeriod() throws Exception { @@ -35,7 +36,7 @@ public void createsDatabaseWithVersionRetentionPeriod() throws Exception { final String out = SampleRunner.runSample(() -> CreateDatabaseWithVersionRetentionPeriodSample .createDatabaseWithVersionRetentionPeriod( - databaseAdminClient, instanceId, databaseId, versionRetentionPeriod + projectId, instanceId, databaseId, versionRetentionPeriod )); assertThat(out).contains( diff --git a/samples/snippets/src/test/java/com/example/spanner/CreateInstanceWithAutoscalingConfigSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/CreateInstanceWithAutoscalingConfigSampleIT.java index 76eef2529d..041d6b97ac 100644 --- a/samples/snippets/src/test/java/com/example/spanner/CreateInstanceWithAutoscalingConfigSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/CreateInstanceWithAutoscalingConfigSampleIT.java @@ -1,5 +1,5 @@ /* - * 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. @@ -18,25 +18,19 @@ import static com.google.common.truth.Truth.assertThat; -import com.google.cloud.spanner.InstanceId; -import java.util.UUID; +import com.google.spanner.admin.database.v1.InstanceName; import org.junit.Test; -public class CreateInstanceWithAutoscalingConfigSampleIT extends SampleTestBase { +public class CreateInstanceWithAutoscalingConfigSampleIT extends SampleTestBaseV2 { @Test public void testCreateInstanceWithAutoscalingConfig() throws Exception { - String instanceId = String.format("autoscaler-%s", UUID.randomUUID()); + String instanceId = idGenerator.generateInstanceId(); String out = SampleRunner.runSample( - () -> { - try { - CreateInstanceWithAutoscalingConfigExample.createInstance(projectId, instanceId); - } finally { - spanner.getInstanceAdminClient().deleteInstance(instanceId); - } - }); + () -> CreateInstanceWithAutoscalingConfigExample.createInstance(projectId, instanceId)); assertThat(out) - .contains(String.format("Autoscaler instance %s", InstanceId.of(projectId, instanceId))); + .contains(String.format("Autoscaler instance %s", + InstanceName.of(projectId, instanceId).toString())); } } diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateInstanceWithProcessingUnitsSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/CreateInstanceWithProcessingUnitsSampleIT.java similarity index 93% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateInstanceWithProcessingUnitsSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/CreateInstanceWithProcessingUnitsSampleIT.java index 13778dff82..dcddea4929 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateInstanceWithProcessingUnitsSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/CreateInstanceWithProcessingUnitsSampleIT.java @@ -14,11 +14,10 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner; import static com.google.common.truth.Truth.assertThat; -import com.example.spanner.SampleRunner; import com.google.spanner.admin.database.v1.InstanceName; import org.junit.Test; diff --git a/samples/snippets/src/test/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSampleIT.java index b2dd6638ce..481bdc16bd 100644 --- a/samples/snippets/src/test/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSampleIT.java @@ -18,28 +18,30 @@ import static org.junit.Assert.assertTrue; -import java.util.Arrays; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.InstanceName; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class CreateTableWithForeignKeyDeleteCascadeSampleIT extends SampleTestBase { +public class CreateTableWithForeignKeyDeleteCascadeSampleIT extends SampleTestBaseV2 { @Test public void testCreateTableWithForeignKeyDeleteCascade() throws Exception { // Creates database final String databaseId = idGenerator.generateDatabaseId(); - databaseAdminClient - .createDatabase(instanceId, databaseId, Arrays.asList()) - .get(5, TimeUnit.MINUTES); + final CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .setParent(InstanceName.of(projectId, instanceId).toString()).build(); + databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample( () -> CreateTableWithForeignKeyDeleteCascadeSample - .createForeignKeyDeleteCascadeConstraint( - databaseAdminClient, instanceId, databaseId)); + .createForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId)); assertTrue( "Expected to have created database " diff --git a/samples/snippets/src/test/java/com/example/spanner/CustomInstanceConfigSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/CustomInstanceConfigSampleIT.java index ba1eef6850..354e11a504 100644 --- a/samples/snippets/src/test/java/com/example/spanner/CustomInstanceConfigSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/CustomInstanceConfigSampleIT.java @@ -1,11 +1,11 @@ /* - * Copyright 2022 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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,8 +19,11 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; -public class CustomInstanceConfigSampleIT extends SampleTestBase { +@RunWith(JUnit4.class) +public class CustomInstanceConfigSampleIT extends SampleTestBaseV2 { @Test public void testCustomInstanceConfigOperations() throws Exception { @@ -34,26 +37,37 @@ public void testCustomInstanceConfigOperations() throws Exception { projectId, instanceConfigName, customInstanceConfigId)); assertTrue(out1.contains("Created instance configuration")); - // List the instance config operations. + // Fetch the instance config that was created above. final String out2 = + SampleRunner.runSample( + () -> GetInstanceConfigSample.getInstanceConfig(projectId, instanceConfigName)); + assertTrue(out2.contains("Available leader options for instance config")); + + // Fetch the instance config that was created above. + final String out3 = + SampleRunner.runSample( + () -> ListInstanceConfigsSample.listInstanceConfigs(projectId)); + assertTrue(out3.contains("Available leader options for instance config")); + + // List the instance config operations. + final String out4 = SampleRunner.runSample( () -> ListInstanceConfigOperationsSample.listInstanceConfigOperations(projectId)); - assertTrue(out2.contains("List instance config operation")); + assertTrue(out4.contains("Obtained list of instance config operations")); // Update display name to a randomly generated instance config id. - final String out3 = + final String out5 = SampleRunner.runSample( () -> - UpdateInstanceConfigSample.updateInstanceConfig( - projectId, customInstanceConfigId)); - assertTrue(out3.contains("Updated instance configuration")); + UpdateInstanceConfigSample.updateInstanceConfig(projectId, customInstanceConfigId)); + assertTrue(out5.contains("Updated instance configuration")); // Delete the created instance config. - final String out4 = + final String out6 = SampleRunner.runSample( () -> DeleteInstanceConfigSample.deleteInstanceConfig(projectId, customInstanceConfigId)); - assertTrue(out4.contains("Deleted instance configuration")); + assertTrue(out6.contains("Deleted instance configuration")); } } diff --git a/samples/snippets/src/test/java/com/example/spanner/DatabaseRolesIT.java b/samples/snippets/src/test/java/com/example/spanner/DatabaseRolesIT.java index b0a506430a..6c2b41c367 100644 --- a/samples/snippets/src/test/java/com/example/spanner/DatabaseRolesIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/DatabaseRolesIT.java @@ -22,7 +22,8 @@ import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; import java.util.Arrays; import java.util.Collections; import java.util.concurrent.TimeUnit; @@ -33,20 +34,24 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Integration tests for FGAC samples for GoogleStandardSql dialect. */ +/** + * Integration tests for FGAC samples for GoogleStandardSql dialect. + */ @RunWith(JUnit4.class) -public class DatabaseRolesIT extends SampleTestBase { +public class DatabaseRolesIT extends SampleTestBaseV2 { private static DatabaseId databaseId; @BeforeClass public static void createTestDatabase() throws Exception { final String database = idGenerator.generateDatabaseId(); - databaseAdminClient - .createDatabase( - instanceId, - database, - ImmutableList.of( + final CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setParent( + com.google.spanner.admin.database.v1.InstanceName.of(projectId, instanceId) + .toString()) + .setCreateStatement("CREATE DATABASE `" + database + "`") + .addAllExtraStatements(Lists.newArrayList( "CREATE TABLE Singers (" + " SingerId INT64 NOT NULL," + " FirstName STRING(1024)," @@ -61,8 +66,8 @@ public static void createTestDatabase() throws Exception { + " AlbumTitle STRING(MAX)," + " MarketingBudget INT64" + ") PRIMARY KEY (SingerId, AlbumId)," - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")) - .get(10, TimeUnit.MINUTES); + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).build(); + databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); databaseId = DatabaseId.of(projectId, instanceId, database); } @@ -103,7 +108,7 @@ public void testAddAndDropDatabaseRole() throws Exception { SampleRunner.runSample( () -> AddAndDropDatabaseRole.addAndDropDatabaseRole( - projectId, instanceId, databaseId.getDatabase(), "new-parent", "new-child")); + projectId, instanceId, databaseId.getDatabase(), "new_parent", "new_child")); assertTrue(out.contains("Created roles new_parent and new_child and granted privileges")); assertTrue(out.contains("Revoked privileges and dropped role new_child")); } @@ -115,7 +120,7 @@ public void testListDatabaseRoles() throws Exception { () -> ListDatabaseRoles.listDatabaseRoles( projectId, instanceId, databaseId.getDatabase())); - assertTrue(out.contains("new_parent")); + assertTrue(out.contains("Obtained role ")); } @Test diff --git a/samples/snippets/src/test/java/com/example/spanner/DropForeignKeyConstraintDeleteCascadeSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/DropForeignKeyConstraintDeleteCascadeSampleIT.java index 1c58daded1..2e763949f4 100644 --- a/samples/snippets/src/test/java/com/example/spanner/DropForeignKeyConstraintDeleteCascadeSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/DropForeignKeyConstraintDeleteCascadeSampleIT.java @@ -18,22 +18,24 @@ import static org.junit.Assert.assertTrue; -import java.util.Arrays; +import com.google.common.collect.Lists; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.InstanceName; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class DropForeignKeyConstraintDeleteCascadeSampleIT extends SampleTestBase { +public class DropForeignKeyConstraintDeleteCascadeSampleIT extends SampleTestBaseV2 { @Test public void testDropForeignKeyConstraintDeleteCascade() throws Exception { // Creates database final String databaseId = idGenerator.generateDatabaseId(); - databaseAdminClient - .createDatabase( - instanceId, - databaseId, - Arrays.asList( + final CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .setParent(InstanceName.of(projectId, instanceId).toString()) + .addAllExtraStatements(Lists.newArrayList( "CREATE TABLE Customers (\n" + " CustomerId INT64 NOT NULL,\n" + " CustomerName STRING(62) NOT NULL,\n" @@ -45,15 +47,15 @@ public void testDropForeignKeyConstraintDeleteCascade() throws Exception { + " CONSTRAINT FKShoppingCartsCustomerName" + " FOREIGN KEY (CustomerName)\n" + " REFERENCES Customers (CustomerName) ON DELETE CASCADE\n" - + " ) PRIMARY KEY (CartId)\n")) - .get(5, TimeUnit.MINUTES); + + " ) PRIMARY KEY (CartId)\n")).build(); + databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample( () -> DropForeignKeyConstraintDeleteCascadeSample.deleteForeignKeyDeleteCascadeConstraint( - databaseAdminClient, instanceId, databaseId)); + projectId, instanceId, databaseId)); assertTrue( "Expected to have dropped foreign-key constraints from tables in created database " diff --git a/samples/snippets/src/test/java/com/example/spanner/EncryptionKeyIT.java b/samples/snippets/src/test/java/com/example/spanner/EncryptionKeyIT.java index 03aa10a55f..2470540914 100644 --- a/samples/snippets/src/test/java/com/example/spanner/EncryptionKeyIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/EncryptionKeyIT.java @@ -18,11 +18,14 @@ import static com.google.common.truth.Truth.assertThat; +import com.example.spanner.admin.archived.CreateDatabaseWithEncryptionKey; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Uninterruptibles; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.InstanceName; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import org.junit.BeforeClass; @@ -32,12 +35,13 @@ import org.junit.runners.JUnit4; /** - * Integration tests for: {@link CreateDatabaseWithEncryptionKey}, {@link - * CreateBackupWithEncryptionKey} and {@link RestoreBackupWithEncryptionKey} + * Integration tests for: {@link CreateDatabaseWithEncryptionKey}, + * {@link com.example.spanner.admin.archived.CreateBackupWithEncryptionKey} and + * {@link com.example.spanner.admin.archived.RestoreBackupWithEncryptionKey} */ @RunWith(JUnit4.class) @Ignore -public class EncryptionKeyIT extends SampleTestBase { +public class EncryptionKeyIT extends SampleTestBaseV2 { private static String key; @@ -58,16 +62,10 @@ public void testEncryptedDatabaseAndBackupAndRestore() throws Exception { final String restoreId = idGenerator.generateDatabaseId(); String out = SampleRunner.runSample(() -> - CreateDatabaseWithEncryptionKey.createDatabaseWithEncryptionKey( - databaseAdminClient, - projectId, - instanceId, - databaseId, - key - )); - assertThat(out).contains( - "Database projects/" + projectId + "/instances/" + instanceId + "/databases/" + databaseId - + " created with encryption key " + key); + SpannerSample.createDatabase( + databaseAdminClient, InstanceName.of(projectId, instanceId), databaseId)); + assertThat(out).contains(String.format( + "Created database [%s]", DatabaseName.of(projectId, instanceId, databaseId))); out = SampleRunner.runSampleWithRetry(() -> CreateBackupWithEncryptionKey.createBackupWithEncryptionKey( diff --git a/samples/snippets/src/test/java/com/example/spanner/GetDatabaseDdlSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/GetDatabaseDdlSampleIT.java index a345aa7156..a50f55e355 100644 --- a/samples/snippets/src/test/java/com/example/spanner/GetDatabaseDdlSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/GetDatabaseDdlSampleIT.java @@ -18,42 +18,44 @@ import static org.junit.Assert.assertTrue; -import com.google.cloud.spanner.InstanceConfig; -import com.google.cloud.spanner.InstanceConfigId; -import java.util.Arrays; +import com.google.common.collect.Lists; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.instance.v1.InstanceConfig; +import com.google.spanner.admin.instance.v1.InstanceName; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class GetDatabaseDdlSampleIT extends SampleTestBase { +public class GetDatabaseDdlSampleIT extends SampleTestBaseV2 { @Test public void testGetDatabaseDdl() throws Exception { // Finds a possible new leader option - final InstanceConfigId instanceConfigId = instanceAdminClient - .getInstance(multiRegionalInstanceId) - .getInstanceConfigId(); - final InstanceConfig config = instanceAdminClient - .getInstanceConfig(instanceConfigId.getInstanceConfig()); + final String instanceConfigId = instanceAdminClient.getInstance( + InstanceName.of(projectId, multiRegionalInstanceId)).getConfig(); + final InstanceConfig config = instanceAdminClient.getInstanceConfig(instanceConfigId); assertTrue( "Expected instance config " + instanceConfigId + " to have at least one leader option", - config.getLeaderOptions().size() > 0 + config.getLeaderOptionsList().size() > 0 ); - final String defaultLeader = config.getLeaderOptions().get(0); + final String defaultLeader = config.getLeaderOptions(0); // Creates database final String databaseId = idGenerator.generateDatabaseId(); - databaseAdminClient.createDatabase( - multiRegionalInstanceId, - databaseId, - Arrays.asList( - "CREATE TABLE Singers (Id INT64 NOT NULL) PRIMARY KEY (Id)", - "ALTER DATABASE `" - + databaseId - + "` SET OPTIONS ( default_leader = '" - + defaultLeader - + "')" - ) - ).get(5, TimeUnit.MINUTES); + final CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setParent( + com.google.spanner.admin.database.v1.InstanceName.of(projectId, + multiRegionalInstanceId).toString()) + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .addAllExtraStatements(Lists.newArrayList( + "CREATE TABLE Singers (Id INT64 NOT NULL) PRIMARY KEY (Id)", + "ALTER DATABASE `" + + databaseId + + "` SET OPTIONS ( default_leader = '" + + defaultLeader + + "')" + )).build(); + databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample(() -> GetDatabaseDdlSample diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/ListDatabasesIT.java b/samples/snippets/src/test/java/com/example/spanner/ListDatabasesIT.java similarity index 92% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/ListDatabasesIT.java rename to samples/snippets/src/test/java/com/example/spanner/ListDatabasesIT.java index 730205b8b4..ce3e56bc64 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/ListDatabasesIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/ListDatabasesIT.java @@ -14,11 +14,10 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner; import static org.junit.Assert.assertTrue; -import com.example.spanner.SampleRunner; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/samples/snippets/src/test/java/com/example/spanner/PgCaseSensitivitySampleIT.java b/samples/snippets/src/test/java/com/example/spanner/PgCaseSensitivitySampleIT.java index 1c2bca587c..fca4ac55c0 100644 --- a/samples/snippets/src/test/java/com/example/spanner/PgCaseSensitivitySampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/PgCaseSensitivitySampleIT.java @@ -18,24 +18,22 @@ import static org.junit.Assert.assertTrue; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; -import java.util.Collections; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.DatabaseDialect; +import com.google.spanner.admin.database.v1.InstanceName; import org.junit.Test; -public class PgCaseSensitivitySampleIT extends SampleTestBase { +public class PgCaseSensitivitySampleIT extends SampleTestBaseV2 { @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 CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setCreateStatement(getCreateDatabaseStatement(databaseId, DatabaseDialect.POSTGRESQL)) + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setDatabaseDialect(DatabaseDialect.POSTGRESQL).build(); + databaseAdminClient.createDatabaseAsync(request).get(); final String out = SampleRunner.runSample( diff --git a/samples/snippets/src/test/java/com/example/spanner/PgInterleavedTableSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/PgInterleavedTableSampleIT.java index 6678f2a471..412147da0b 100644 --- a/samples/snippets/src/test/java/com/example/spanner/PgInterleavedTableSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/PgInterleavedTableSampleIT.java @@ -18,24 +18,22 @@ import static org.junit.Assert.assertTrue; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; -import java.util.Collections; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.DatabaseDialect; +import com.google.spanner.admin.database.v1.InstanceName; import org.junit.Test; -public class PgInterleavedTableSampleIT extends SampleTestBase { +public class PgInterleavedTableSampleIT extends SampleTestBaseV2 { @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 CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setCreateStatement(getCreateDatabaseStatement(databaseId, DatabaseDialect.POSTGRESQL)) + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setDatabaseDialect(DatabaseDialect.POSTGRESQL).build(); + databaseAdminClient.createDatabaseAsync(request).get(); final String out = SampleRunner.runSample( diff --git a/samples/snippets/src/test/java/com/example/spanner/PgSpannerSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/PgSpannerSampleIT.java index 796df092c8..d55af6203d 100644 --- a/samples/snippets/src/test/java/com/example/spanner/PgSpannerSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/PgSpannerSampleIT.java @@ -19,17 +19,18 @@ import static com.google.common.truth.Truth.assertThat; import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.InstanceName; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.PrintStream; -import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; -import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -40,26 +41,23 @@ */ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") -public class PgSpannerSampleIT { +public class PgSpannerSampleIT extends SampleTestBaseV2 { + private static final int DBID_LENGTH = 20; // The instance needs to exist for tests to pass. private static final String instanceId = System.getProperty("spanner.test.instance"); private static final String baseDbId = System.getProperty("spanner.sample.database"); - private static final String databaseId = formatForTest(baseDbId); - private static final String encryptedDatabaseId = formatForTest(baseDbId); - private static final String encryptedBackupId = formatForTest(baseDbId); - private static final String encryptedRestoreId = formatForTest(baseDbId); static Spanner spanner; static DatabaseId dbId; static DatabaseAdminClient dbClient; @BeforeClass - public static void setUp() { + public static void setUp() throws IOException { SpannerOptions options = SpannerOptions.newBuilder().setAutoThrottleAdministrativeRequests().build(); spanner = options.getService(); - dbClient = spanner.getDatabaseAdminClient(); - dbId = DatabaseId.of(options.getProjectId(), instanceId, databaseId); + dbClient = DatabaseAdminClient.create(); + dbId = DatabaseId.of(options.getProjectId(), instanceId, idGenerator.generateDatabaseId()); // Delete stale test databases that have been created earlier by this test, but not deleted. deleteStaleTestDatabases(); } @@ -68,34 +66,25 @@ static void deleteStaleTestDatabases() { Timestamp now = Timestamp.now(); Pattern samplePattern = getTestDbIdPattern(PgSpannerSampleIT.baseDbId); Pattern restoredPattern = getTestDbIdPattern("restored"); - for (Database db : dbClient.listDatabases(PgSpannerSampleIT.instanceId).iterateAll()) { + for (Database db : dbClient.listDatabases( + InstanceName.of(projectId, instanceId)).iterateAll()) { + DatabaseName databaseName = DatabaseName.parse(db.getName()); if (TimeUnit.HOURS.convert(now.getSeconds() - db.getCreateTime().getSeconds(), TimeUnit.SECONDS) > 24) { - if (db.getId().getDatabase().length() >= DBID_LENGTH) { - if (samplePattern.matcher(toComparableId(PgSpannerSampleIT.baseDbId, - db.getId().getDatabase())).matches()) { - db.drop(); + if (databaseName.getDatabase().length() >= DBID_LENGTH) { + if (samplePattern.matcher( + toComparableId(PgSpannerSampleIT.baseDbId, databaseName.getDatabase())).matches()) { + dbClient.dropDatabase(db.getName()); } - if (restoredPattern.matcher(toComparableId("restored", db.getId().getDatabase())) + if (restoredPattern.matcher(toComparableId("restored", databaseName.getDatabase())) .matches()) { - db.drop(); + dbClient.dropDatabase(db.getName()); } } } } } - @AfterClass - public static void tearDown() { - dbClient.dropDatabase(dbId.getInstanceId().getInstance(), dbId.getDatabase()); - dbClient.dropDatabase( - dbId.getInstanceId().getInstance(), SpannerSample.createRestoredSampleDbId(dbId)); - dbClient.dropDatabase(instanceId, encryptedDatabaseId); - dbClient.dropDatabase(instanceId, encryptedRestoreId); - dbClient.deleteBackup(instanceId, encryptedBackupId); - spanner.close(); - } - private static String toComparableId(String baseId, String existingId) { String zeroUuid = "00000000-0000-0000-0000-0000-00000000"; int shouldBeLength = (baseId + "-" + zeroUuid).length(); @@ -109,17 +98,13 @@ private static Pattern getTestDbIdPattern(String baseDbId) { Pattern.CASE_INSENSITIVE); } - static String formatForTest(String name) { - return name + "-" + UUID.randomUUID().toString().substring(0, DBID_LENGTH); - } - - private String runSample(String command) { + private String runSample(String command) throws Exception { final PrintStream stdOut = System.out; final ByteArrayOutputStream bout = new ByteArrayOutputStream(); final PrintStream out = new PrintStream(bout); System.setOut(out); - System.out.println(instanceId + ":" + databaseId); - PgSpannerSample.main(new String[]{command, instanceId, databaseId}); + System.out.println(instanceId + ":" + dbId.getDatabase()); + PgSpannerSample.main(new String[]{command, instanceId, dbId.getDatabase()}); System.setOut(stdOut); return bout.toString(); } @@ -127,7 +112,7 @@ private String runSample(String command) { @Test public void testSample() throws Exception { assertThat(instanceId).isNotNull(); - assertThat(databaseId).isNotNull(); + assertThat(dbId.getDatabase()).isNotNull(); System.out.println("Create Database ..."); String out = runSample("createpgdatabase"); diff --git a/samples/snippets/src/test/java/com/example/spanner/PgSpannerStandaloneExamplesIT.java b/samples/snippets/src/test/java/com/example/spanner/PgSpannerStandaloneExamplesIT.java index d8e5b0c9c5..c906006ef5 100644 --- a/samples/snippets/src/test/java/com/example/spanner/PgSpannerStandaloneExamplesIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/PgSpannerStandaloneExamplesIT.java @@ -16,6 +16,7 @@ package com.example.spanner; +import static com.example.spanner.SpannerSampleIT.formatForTest; import static com.google.common.truth.Truth.assertThat; import com.google.api.gax.longrunning.OperationFuture; @@ -52,7 +53,7 @@ public class PgSpannerStandaloneExamplesIT { // The instance needs to exist for tests to pass. private static String instanceId = System.getProperty("spanner.test.instance"); private static String baseDatabaseId = System.getProperty("spanner.sample.database", "mysample"); - private static String databaseId = SpannerSampleIT.formatForTest(baseDatabaseId); + private static String databaseId = formatForTest(baseDatabaseId); private static DatabaseId dbId; private static DatabaseAdminClient dbClient; private static Spanner spanner; @@ -157,7 +158,7 @@ public void addNumericColumn_shouldSuccessfullyAddColumn() () -> { try { AddNumericColumnSample.addNumericColumn( - spanner.getDatabaseAdminClient(), instanceId, databaseId); + spanner.getOptions().getProjectId(), instanceId, databaseId); } catch (ExecutionException e) { System.out.printf( "Adding column `Revenue` failed: %s%n", e.getCause().getMessage()); @@ -226,7 +227,7 @@ public void addJsonbColumn_shouldSuccessfullyAddColumn() () -> { try { AddJsonbColumnSample.addJsonbColumn( - spanner.getDatabaseAdminClient(), instanceId, databaseId); + spanner.getOptions().getProjectId(), instanceId, databaseId); } catch (ExecutionException e) { System.out.printf( "Adding column `VenueDetails` failed: %s%n", e.getCause().getMessage()); diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/SampleTestBaseV2.java b/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2.java similarity index 99% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/SampleTestBaseV2.java rename to samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2.java index 32e1c26fcb..909e79738b 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/SampleTestBaseV2.java +++ b/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner; import com.example.spanner.SampleIdGenerator; import com.google.cloud.spanner.Spanner; diff --git a/samples/snippets/src/test/java/com/example/spanner/SequenceSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/SequenceSampleIT.java index c8174ff4ca..de2c3961c2 100644 --- a/samples/snippets/src/test/java/com/example/spanner/SequenceSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/SequenceSampleIT.java @@ -20,10 +20,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; import com.google.common.collect.ImmutableList; -import java.util.Collections; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.DatabaseDialect; import java.util.HashSet; import java.util.concurrent.TimeUnit; import org.junit.Before; @@ -38,23 +37,23 @@ * dialects. */ @RunWith(Parameterized.class) -public class SequenceSampleIT extends SampleTestBase { +public class SequenceSampleIT extends SampleTestBaseV2 { - private static DatabaseId databaseId; + private static String databaseId; /** * Set of dialects for which database has already been created in this test suite. This helps in * limiting the number of databases created per dialect to one. */ - private static final HashSet dbInitializedDialects = new HashSet<>(); + private static final HashSet dbInitializedDialects = new HashSet<>(); @Parameters(name = "dialect = {0}") - public static Iterable data() { - return ImmutableList.of(Dialect.GOOGLE_STANDARD_SQL, Dialect.POSTGRESQL); + public static Iterable data() { + return ImmutableList.of(DatabaseDialect.GOOGLE_STANDARD_SQL, DatabaseDialect.POSTGRESQL); } @Parameter(0) - public static Dialect dialect; + public static DatabaseDialect dialect; @Before public void createTestDatabase() throws Exception { @@ -63,37 +62,36 @@ public void createTestDatabase() throws Exception { return; } dbInitializedDialects.add(dialect); - final String database = idGenerator.generateDatabaseId(); + databaseId = idGenerator.generateDatabaseId(); + CreateDatabaseRequest createDatabaseRequest = + CreateDatabaseRequest.newBuilder() + .setParent(getInstanceName(projectId, instanceId)) + .setCreateStatement(getCreateDatabaseStatement(databaseId, dialect)) + .setDatabaseDialect(dialect).build(); databaseAdminClient - .createDatabase( - databaseAdminClient - .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, database)) - .setDialect(dialect) - .build(), - Collections.emptyList()) + .createDatabaseAsync(createDatabaseRequest) .get(10, TimeUnit.MINUTES); - databaseId = DatabaseId.of(projectId, instanceId, database); } @Test public void createSequence() throws Exception { String out; - if (dialect == Dialect.GOOGLE_STANDARD_SQL) { + if (dialect == DatabaseDialect.GOOGLE_STANDARD_SQL) { out = runSample( () -> CreateSequenceSample.createSequence( - projectId, instanceId, databaseId.getDatabase())); + projectId, instanceId, databaseId)); } else { out = runSample( () -> PgCreateSequenceSample.pgCreateSequence( - projectId, instanceId, databaseId.getDatabase())); + projectId, instanceId, databaseId)); } assertTrue( out.contains( - "Created Seq sequence and Customers table, where its key column " + "Created Seq sequence and Customers table, where the key column " + "CustomerId uses the sequence as a default value")); assertEquals(out.split("Inserted customer record with CustomerId", -1).length - 1, 3); assertTrue(out.contains("Number of customer records inserted is: 3")); @@ -102,18 +100,18 @@ public void createSequence() throws Exception { @Test public void alterSequence() throws Exception { String out; - if (dialect == Dialect.GOOGLE_STANDARD_SQL) { + if (dialect == DatabaseDialect.GOOGLE_STANDARD_SQL) { out = runSample( () -> AlterSequenceSample.alterSequence( - projectId, instanceId, databaseId.getDatabase())); + projectId, instanceId, databaseId)); } else { out = runSample( () -> PgAlterSequenceSample.pgAlterSequence( - projectId, instanceId, databaseId.getDatabase())); + projectId, instanceId, databaseId)); } assertTrue( out.contains("Altered Seq sequence to skip an inclusive range between 1000 and 5000000")); @@ -124,17 +122,17 @@ public void alterSequence() throws Exception { @Test public void dropSequence() throws Exception { String out; - if (dialect == Dialect.GOOGLE_STANDARD_SQL) { + if (dialect == DatabaseDialect.GOOGLE_STANDARD_SQL) { out = runSample( () -> - DropSequenceSample.dropSequence(projectId, instanceId, databaseId.getDatabase())); + DropSequenceSample.dropSequence(projectId, instanceId, databaseId)); } else { out = runSample( () -> PgDropSequenceSample.pgDropSequence( - projectId, instanceId, databaseId.getDatabase())); + projectId, instanceId, databaseId)); } assertTrue( out.contains( diff --git a/samples/snippets/src/test/java/com/example/spanner/SpannerSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/SpannerSampleIT.java index 72e8c36d76..422d7618de 100644 --- a/samples/snippets/src/test/java/com/example/spanner/SpannerSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/SpannerSampleIT.java @@ -20,10 +20,6 @@ import static org.junit.Assert.assertTrue; import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Backup; -import com.google.cloud.spanner.BackupId; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Instance; @@ -36,26 +32,35 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Uninterruptibles; +import com.google.spanner.admin.database.v1.Backup; +import com.google.spanner.admin.database.v1.BackupName; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.InstanceName; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.PrintStream; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import java.util.regex.Pattern; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.threeten.bp.LocalDate; -import org.threeten.bp.temporal.ChronoField; -/** Unit tests for {@code SpannerSample} */ +/** + * Unit tests for {@code SpannerSample} + */ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") -public class SpannerSampleIT { +public class SpannerSampleIT extends SampleTestBaseV2 { + private static final int DBID_LENGTH = 20; // The instance needs to exist for tests to pass. private static final String instanceId = System.getProperty("spanner.test.instance"); @@ -66,24 +71,30 @@ public class SpannerSampleIT { Preconditions.checkNotNull(System.getProperty("spanner.test.key.ring")); private static final String keyName = Preconditions.checkNotNull(System.getProperty("spanner.test.key.name")); - private static final String databaseId = formatForTest(baseDbId); - private static final String encryptedDatabaseId = formatForTest(baseDbId); private static final String encryptedBackupId = formatForTest(baseDbId); - private static final String encryptedRestoreId = formatForTest(baseDbId); private static final long STALE_INSTANCE_THRESHOLD_SECS = TimeUnit.SECONDS.convert(24L, TimeUnit.HOURS); static Spanner spanner; - static DatabaseId dbId; - static DatabaseAdminClient dbClient; + static DatabaseAdminClient databaseAdminClient; private static String key; private long lastUpdateDataTimeInMillis; - private String runSample(String command) throws Exception { + private String runSample(String command, String databaseId) throws Exception { PrintStream stdOut = System.out; ByteArrayOutputStream bout = new ByteArrayOutputStream(); PrintStream out = new PrintStream(bout); System.setOut(out); - SpannerSample.main(new String[] {command, instanceId, databaseId}); + SpannerSample.main(new String[]{command, instanceId, databaseId, null}); + System.setOut(stdOut); + return bout.toString(); + } + + private String runSample(String command, String databaseId, String backupId) throws Exception { + PrintStream stdOut = System.out; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(bout); + System.setOut(out); + SpannerSample.main(new String[]{command, instanceId, databaseId, backupId}); System.setOut(stdOut); return bout.toString(); } @@ -93,10 +104,9 @@ public static void setUp() throws Exception { SpannerOptions options = SpannerOptions.newBuilder().setAutoThrottleAdministrativeRequests().build(); spanner = options.getService(); - dbClient = spanner.getDatabaseAdminClient(); - dbId = DatabaseId.of(options.getProjectId(), instanceId, databaseId); + databaseAdminClient = DatabaseAdminClient.create(); // Delete stale test databases that have been created earlier by this test, but not deleted. - deleteStaleTestDatabases(instanceId, baseDbId); + deleteStaleTestDatabases(); key = String.format( "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", @@ -132,20 +142,25 @@ private static void deleteStaleEncryptedTestInstances() throws InterruptedExcept } } - static void deleteStaleTestDatabases(String instanceId, String baseDbId) { + static void deleteStaleTestDatabases() throws IOException { Timestamp now = Timestamp.now(); - Pattern samplePattern = getTestDbIdPattern(baseDbId); + Pattern samplePattern = getTestDbIdPattern(SpannerSampleIT.baseDbId); Pattern restoredPattern = getTestDbIdPattern("restored"); - for (Database db : dbClient.listDatabases(instanceId).iterateAll()) { - if (TimeUnit.HOURS.convert(now.getSeconds() - db.getCreateTime().getSeconds(), - TimeUnit.SECONDS) > 24) { - if (db.getId().getDatabase().length() >= DBID_LENGTH) { - if (samplePattern.matcher(toComparableId(baseDbId, db.getId().getDatabase())).matches()) { - db.drop(); - } - if (restoredPattern.matcher(toComparableId("restored", db.getId().getDatabase())) - .matches()) { - db.drop(); + try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) { + for (Database db : databaseAdminClient.listDatabases(InstanceName.of(projectId, instanceId)) + .iterateAll()) { + DatabaseName databaseName = DatabaseName.parse(db.getName()); + if (TimeUnit.HOURS.convert(now.getSeconds() - db.getCreateTime().getSeconds(), + TimeUnit.SECONDS) > 24) { + if (databaseName.getDatabase().length() >= DBID_LENGTH) { + if (samplePattern.matcher( + toComparableId(SpannerSampleIT.baseDbId, databaseName.getDatabase())).matches()) { + databaseAdminClient.dropDatabase(db.getName()); + } + if (restoredPattern.matcher(toComparableId("restored", databaseName.getDatabase())) + .matches()) { + databaseAdminClient.dropDatabase(db.getName()); + } } } } @@ -153,305 +168,355 @@ static void deleteStaleTestDatabases(String instanceId, String baseDbId) { } @AfterClass - public static void tearDown() throws Exception { - dbClient.dropDatabase(dbId.getInstanceId().getInstance(), dbId.getDatabase()); - dbClient.dropDatabase( - dbId.getInstanceId().getInstance(), SpannerSample.createRestoredSampleDbId(dbId)); - dbClient.dropDatabase(instanceId, encryptedDatabaseId); - dbClient.dropDatabase(instanceId, encryptedRestoreId); - dbClient.deleteBackup(instanceId, encryptedBackupId); + public static void tearDown() { + databaseAdminClient.deleteBackup(BackupName.of(projectId, instanceId, encryptedBackupId)); spanner.close(); } @Test public void testSample() throws Exception { + String databaseId = idGenerator.generateDatabaseId(); + DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); assertThat(instanceId).isNotNull(); assertThat(databaseId).isNotNull(); - String out = runSample("createdatabase"); + String out = runSample("createdatabase", databaseId); assertThat(out).contains("Created database"); assertThat(out).contains(dbId.getName()); - runSample("write"); + System.out.println("Write data to sample tables ..."); + runSample("write", databaseId); - out = runSample("delete"); + System.out.println("Delete data to sample tables ..."); + out = runSample("delete", databaseId); assertThat(out).contains("Records deleted."); - runSample("write"); + runSample("write", databaseId); - out = runSample("read"); + System.out.println("Read data from sample tables ..."); + out = runSample("read", databaseId); assertThat(out).contains("1 1 Total Junk"); - out = runSample("query"); + out = runSample("query", databaseId); assertThat(out).contains("1 1 Total Junk"); - runSample("addmarketingbudget"); + runSample("addmarketingbudget", databaseId); // wait for 15 seconds to elapse and then run an update, and query for stale data lastUpdateDataTimeInMillis = System.currentTimeMillis(); while (System.currentTimeMillis() < lastUpdateDataTimeInMillis + 16000) { Thread.sleep(1000); } - runSample("update"); - out = runSample("readstaledata"); + runSample("update", databaseId); + + System.out.println("Read stale data from sample tables ..."); + out = runSample("readstaledata", databaseId); assertThat(out).contains("1 1 NULL"); - runSample("writetransaction"); - out = runSample("querymarketingbudget"); + runSample("writetransaction", databaseId); + + System.out.println("Query marketing budget ..."); + out = runSample("querymarketingbudget", databaseId); assertThat(out).contains("1 1 300000"); assertThat(out).contains("2 2 300000"); - runSample("addindex"); - out = runSample("queryindex"); + System.out.println("Add index ..."); + runSample("addindex", databaseId); + + System.out.println("Query index ..."); + out = runSample("queryindex", databaseId); assertThat(out).contains("Go, Go, Go"); assertThat(out).contains("Forever Hold Your Peace"); assertThat(out).doesNotContain("Green"); - out = runSample("readindex"); + System.out.println("Read index ..."); + out = runSample("readindex", databaseId); assertThat(out).contains("Go, Go, Go"); assertThat(out).contains("Forever Hold Your Peace"); assertThat(out).contains("Green"); - runSample("addstoringindex"); - out = runSample("readstoringindex"); + System.out.println("Add Storing index ..."); + runSample("addstoringindex", databaseId); + out = runSample("readstoringindex", databaseId); assertThat(out).contains("300000"); - out = runSample("readonlytransaction"); + System.out.println("Read storing index ..."); + out = runSample("readonlytransaction", databaseId); assertThat(out.replaceAll("[\r\n]+", " ")).containsMatch("(Total Junk.*){2}"); - out = runSample("addcommittimestamp"); + out = runSample("addcommittimestamp", databaseId); assertThat(out).contains("Added LastUpdateTime as a commit timestamp column"); - runSample("updatewithtimestamp"); - out = runSample("querywithtimestamp"); + runSample("updatewithtimestamp", databaseId); + out = runSample("querywithtimestamp", databaseId); assertThat(out).contains("1 1 1000000"); assertThat(out).contains("2 2 750000"); - out = runSample("createtablewithtimestamp"); + out = runSample("createtablewithtimestamp", databaseId); assertThat(out).contains("Created Performances table in database"); - runSample("writewithtimestamp"); - out = runSample("queryperformancestable"); + runSample("writewithtimestamp", databaseId); + out = runSample("queryperformancestable", databaseId); assertThat(out).contains("1 4 2017-10-05 11000"); assertThat(out).contains("1 19 2017-11-02 15000"); assertThat(out).contains("2 42 2017-12-23 7000"); - runSample("writestructdata"); - out = runSample("querywithstruct"); + runSample("writestructdata", databaseId); + out = runSample("querywithstruct", databaseId); assertThat(out).startsWith("6\n"); - out = runSample("querywitharrayofstruct"); + out = runSample("querywitharrayofstruct", databaseId); assertThat(out).startsWith("8\n7\n6"); - out = runSample("querystructfield"); + out = runSample("querystructfield", databaseId); assertThat(out).startsWith("6\n"); - out = runSample("querynestedstructfield"); + out = runSample("querynestedstructfield", databaseId); assertThat(out).contains("6 Imagination\n"); assertThat(out).contains("9 Imagination\n"); - runSample("insertusingdml"); - out = runSample("querysingerstable"); + runSample("insertusingdml", databaseId); + out = runSample("querysingerstable", databaseId); assertThat(out).contains("Virginia Watson"); - runSample("updateusingdml"); - out = runSample("querymarketingbudget"); + runSample("updateusingdml", databaseId); + out = runSample("querymarketingbudget", databaseId); assertThat(out).contains("1 1 2000000"); - runSample("deleteusingdml"); - out = runSample("querysingerstable"); + runSample("deleteusingdml", databaseId); + out = runSample("querysingerstable", databaseId); assertThat(out).doesNotContain("Alice Trentor"); - out = runSample("updateusingdmlwithtimestamp"); + out = runSample("updateusingdmlwithtimestamp", databaseId); assertThat(out).contains("2 records updated"); - out = runSample("writeandreadusingdml"); + out = runSample("writeandreadusingdml", databaseId); assertThat(out).contains("Timothy Campbell"); - runSample("updateusingdmlwithstruct"); - out = runSample("querysingerstable"); + runSample("updateusingdmlwithstruct", databaseId); + out = runSample("querysingerstable", databaseId); assertThat(out).contains("Timothy Grant"); - runSample("writeusingdml"); - out = runSample("querysingerstable"); + runSample("writeusingdml", databaseId); + out = runSample("querysingerstable", databaseId); assertThat(out).contains("Melissa Garcia"); assertThat(out).contains("Russell Morales"); assertThat(out).contains("Jacqueline Long"); assertThat(out).contains("Dylan Shaw"); - out = runSample("querywithparameter"); + out = runSample("querywithparameter", databaseId); assertThat(out).contains("12 Melissa Garcia"); - runSample("writewithtransactionusingdml"); - out = runSample("querymarketingbudget"); + runSample("writewithtransactionusingdml", databaseId); + out = runSample("querymarketingbudget", databaseId); assertThat(out).contains("1 1 2200000"); assertThat(out).contains("2 2 550000"); - runSample("updateusingpartitioneddml"); - out = runSample("querymarketingbudget"); + runSample("updateusingpartitioneddml", databaseId); + out = runSample("querymarketingbudget", databaseId); assertThat(out).contains("1 1 2200000"); assertThat(out).contains("2 2 100000"); - runSample("deleteusingpartitioneddml"); - out = runSample("querysingerstable"); + runSample("deleteusingpartitioneddml", databaseId); + out = runSample("querysingerstable", databaseId); assertThat(out).doesNotContain("Timothy Grant"); assertThat(out).doesNotContain("Melissa Garcia"); assertThat(out).doesNotContain("Russell Morales"); assertThat(out).doesNotContain("Jacqueline Long"); assertThat(out).doesNotContain("Dylan Shaw"); - out = runSample("updateusingbatchdml"); + out = runSample("updateusingbatchdml", databaseId); assertThat(out).contains("1 record updated by stmt 0"); assertThat(out).contains("1 record updated by stmt 1"); - out = runSample("createtablewithdatatypes"); + out = runSample("createtablewithdatatypes", databaseId); assertThat(out).contains("Created Venues table in database"); - runSample("writedatatypesdata"); - out = runSample("querywitharray"); + runSample("writedatatypesdata", databaseId); + out = runSample("querywitharray", databaseId); assertThat(out).contains("19 Venue 19 2020-11-01"); assertThat(out).contains("42 Venue 42 2020-10-01"); - out = runSample("querywithbool"); + out = runSample("querywithbool", databaseId); assertThat(out).contains("19 Venue 19 true"); - out = runSample("querywithbytes"); + out = runSample("querywithbytes", databaseId); assertThat(out).contains("4 Venue 4"); - out = runSample("querywithdate"); + out = runSample("querywithdate", databaseId); assertThat(out).contains("4 Venue 4 2018-09-02"); assertThat(out).contains("42 Venue 42 2018-10-01"); - out = runSample("querywithfloat"); + out = runSample("querywithfloat", databaseId); assertThat(out).contains("4 Venue 4 0.8"); assertThat(out).contains("19 Venue 19 0.9"); - out = runSample("querywithint"); + out = runSample("querywithint", databaseId); assertThat(out).contains("19 Venue 19 6300"); assertThat(out).contains("42 Venue 42 3000"); - out = runSample("querywithstring"); + out = runSample("querywithstring", databaseId); assertThat(out).contains("42 Venue 42"); - out = runSample("querywithtimestampparameter"); + out = runSample("querywithtimestampparameter", databaseId); assertThat(out).contains("4 Venue 4"); assertThat(out).contains("19 Venue 19"); assertThat(out).contains("42 Venue 42"); - out = runSample("querywithnumeric"); + out = runSample("querywithnumeric", databaseId); assertThat(out).contains("19 Venue 19 1200100"); assertThat(out).contains("42 Venue 42 390650.99"); - out = runSample("clientwithqueryoptions"); + out = runSample("clientwithqueryoptions", databaseId); assertThat(out).contains("1 1 Total Junk"); - out = runSample("querywithqueryoptions"); + out = runSample("querywithqueryoptions", databaseId); assertThat(out).contains("1 1 Total Junk"); + } - String backupName = - String.format( - "%s_%02d", - dbId.getDatabase(), LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR)); - BackupId backupId = BackupId.of(dbId.getInstanceId(), backupName); + @Test + public void testBackupSamples_withoutEncryption() { + String databaseId = idGenerator.generateDatabaseId(); + DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); + String restoreDatabaseId = idGenerator.generateDatabaseId(); + String backupId = idGenerator.generateBackupId(); - out = runSample("createbackup"); - assertThat(out).contains("Created backup [" + backupId + "]"); + try { + assertThat(instanceId).isNotNull(); + assertThat(databaseId).isNotNull(); - out = runSample("cancelcreatebackup"); - assertThat(out).contains( - "Backup operation for [" + backupId + "_cancel] successfully"); + System.out.println("Creating Database ..."); + String out = runSample("createdatabase", databaseId); + assertThat(out).contains("Created database"); + assertThat(out).contains(dbId.getName()); - // TODO: remove try-catch when filtering on metadata fields works. - try { - out = runSample("listbackupoperations"); - assertThat(out).contains( - String.format( - "Backup %s on database %s pending:", - backupId.getName(), - dbId.getName())); - assertTrue("Out does not contain copy backup operations", out.contains( - "Copy Backup Operations")); - } catch (SpannerException e) { - assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT); - assertThat(e.getMessage()).contains("Cannot evaluate filter expression"); - } + BackupName backupName = BackupName.of(projectId, instanceId, backupId); - out = runSample("listbackups"); - assertThat(out).contains("All backups:"); - assertThat(out).contains( - String.format("All backups with backup name containing \"%s\":", backupId.getBackup())); - assertThat(out).contains(String.format( - "All backups for databases with a name containing \"%s\":", - dbId.getDatabase())); - assertThat(out).contains( - String.format("All backups that expire before")); - assertThat(out).contains("All backups with size greater than 100 bytes:"); - assertThat(out).containsMatch( - Pattern.compile("All databases created after (.+) and that are ready:")); - assertThat(out).contains("All backups, listed using pagination:"); - // All the above tests should include the created backup exactly once, i.e. exactly 7 times. - assertThat(countOccurrences(out, backupId.getName())).isEqualTo(7); - - // Try the restore operation in a retry loop, as there is a limit on the number of restore - // operations that is allowed to execute simultaneously, and we should retry if we hit this - // limit. - boolean restored = false; - int restoreAttempts = 0; - while (true) { + System.out.println("Creating Backup ..."); + out = runSample("createbackup", databaseId, backupId); + assertThat(out).contains("Created backup [" + backupName.toString() + "]"); + + // TODO: remove try-catch when filtering on metadata fields works. try { - out = runSample("restorebackup"); + System.out.println("List Backup Operations ..."); + out = runSample("listbackupoperations", databaseId, backupId); assertThat(out).contains( - "Restored database [" - + dbId.getName() - + "] from [" - + backupId.getName() - + "]"); - restored = true; - break; + String.format( + "Backup %s on database %s pending:", backupName, dbId.getName())); + assertTrue("Out does not contain copy backup operations", out.contains( + "Copy Backup Operations")); } catch (SpannerException e) { - if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION - && e.getMessage() - .contains("Please retry the operation once the pending restores complete")) { - restoreAttempts++; - if (restoreAttempts == 10) { - System.out.println( - "Restore operation failed 10 times because of other pending restores. " - + "Giving up restore."); - break; + assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT); + assertThat(e.getMessage()).contains("Cannot evaluate filter expression"); + } + + System.out.println("List Backup ..."); + out = runSample("listbackups", databaseId, backupId); + assertThat(out).contains("All backups:"); + assertThat(out).contains( + String.format("All backups with backup name containing \"%s\":", backupId)); + assertThat(out).contains(String.format( + "All backups for databases with a name containing \"%s\":", + dbId.getDatabase())); + assertThat(out).contains( + String.format("All backups that expire before")); + assertThat(out).contains("All backups with size greater than 100 bytes:"); + assertThat(out).containsMatch( + Pattern.compile("All databases created after (.+) and that are ready:")); + assertThat(out).contains("All backups, listed using pagination:"); + // All the above tests should include the created backup exactly once, i.e. exactly 6 times. + assertThat(countOccurrences(out, backupName.toString())).isEqualTo(6); + + // Try the restore operation in a retry loop, as there is a limit on the number of restore + // operations that is allowed to execute simultaneously, and we should retry if we hit this + // limit. + boolean restored = false; + int restoreAttempts = 0; + while (true) { + try { + System.out.println("Restore Backup ..."); + out = runSample("restorebackup", restoreDatabaseId, backupId); + assertThat(out).contains( + "Restored database [" + + DatabaseName.of(projectId, instanceId, restoreDatabaseId).toString() + + "] from [" + + backupName + + "]"); + restored = true; + break; + } catch (SpannerException e) { + if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION + && e.getMessage() + .contains("Please retry the operation once the pending restores complete")) { + restoreAttempts++; + if (restoreAttempts == 10) { + System.out.println( + "Restore operation failed 10 times because of other pending restores. " + + "Giving up restore."); + break; + } + Uninterruptibles.sleepUninterruptibly(60L, TimeUnit.SECONDS); + } else { + throw e; } - Uninterruptibles.sleepUninterruptibly(60L, TimeUnit.SECONDS); - } else { - throw e; } } - } - if (restored) { - out = runSample("listdatabaseoperations"); + if (restored) { + System.out.println("List Database Operations ..."); + out = runSample("listdatabaseoperations", restoreDatabaseId); + assertThat(out).contains( + String.format( + "Database %s restored from backup", + DatabaseId.of(dbId.getInstanceId(), restoreDatabaseId).getName())); + } + + System.out.println("Updating backup ..."); + out = runSample("updatebackup", databaseId, backupId); assertThat(out).contains( - String.format( - "Database %s restored from backup", - DatabaseId.of( - dbId.getInstanceId(), - SpannerSample.createRestoredSampleDbId(dbId)) - .getName())); + String.format("Updated backup [" + backupId + "]")); + + // Drop the restored database before we try to delete the backup. + // Otherwise the delete backup operation might fail as the backup is still in use by + // the OptimizeRestoredDatabase operation. + databaseAdminClient.dropDatabase(DatabaseName.of(projectId, + dbId.getInstanceId().getInstance(), restoreDatabaseId)); + + System.out.println("Deleting Backup ..."); + out = runSample("deletebackup", databaseId, backupId); + assertThat(out).contains("Deleted backup [" + backupId + "]"); + + } catch (Exception ex) { + Assert.fail("Exception raised => " + ex.getCause()); } + } + + @Test + public void testCancelBackupSamples() { + String databaseId = idGenerator.generateDatabaseId(); + DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); + + try { + assertThat(instanceId).isNotNull(); + assertThat(databaseId).isNotNull(); - out = runSample("updatebackup"); - assertThat(out).contains( - String.format("Updated backup [" + backupId + "]")); + String out = runSample("createdatabase", databaseId); + assertThat(out).contains("Created database"); + assertThat(out).contains(dbId.getName()); - // Drop the restored database before we try to delete the backup. - // Otherwise the delete backup operation might fail as the backup is still in use by - // the OptimizeRestoredDatabase operation. - dbClient.dropDatabase( - dbId.getInstanceId().getInstance(), SpannerSample.createRestoredSampleDbId(dbId)); + String backupId = idGenerator.generateBackupId(); - out = runSample("deletebackup"); - assertThat(out).contains("Deleted backup [" + backupId + "]"); + out = runSample("cancelcreatebackup", databaseId, backupId); + assertThat(out).contains( + "Backup operation for [" + backupId + "_cancel] successfully"); + } catch (Exception ex) { + Assert.fail("Exception raised => " + ex.getCause()); + } } @Test public void testEncryptedDatabaseAndBackupSamples() throws Exception { String projectId = spanner.getOptions().getProjectId(); + String databaseId = idGenerator.generateDatabaseId(); + String restoreId = idGenerator.generateDatabaseId(); // Create a separate instance for this test to prevent multiple parallel backup operations on // the same instance that need to wait for each other. - String instanceId = String.format("encrypted-test-%s", UUID.randomUUID()); + String instanceId = idGenerator.generateInstanceId(); InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); instanceAdminClient .createInstance(InstanceInfo.newBuilder(InstanceId.of(projectId, instanceId)) @@ -461,15 +526,15 @@ public void testEncryptedDatabaseAndBackupSamples() throws Exception { .get(); try { String out = SampleRunner - .runSample(() -> CreateDatabaseWithEncryptionKey.createDatabaseWithEncryptionKey(dbClient, - projectId, instanceId, encryptedDatabaseId, key)); + .runSample(() -> SpannerSample.createDatabase( + databaseAdminClient, InstanceName.of(projectId, instanceId), databaseId)); assertThat(out).contains(String.format( - "Database projects/%s/instances/%s/databases/%s created with encryption key %s", - projectId, instanceId, encryptedDatabaseId, key)); + "Created database [%s]", DatabaseName.of(projectId, instanceId, databaseId))); out = SampleRunner.runSampleWithRetry( - () -> CreateBackupWithEncryptionKey.createBackupWithEncryptionKey(dbClient, projectId, - instanceId, encryptedDatabaseId, encryptedBackupId, key), + () -> CreateBackupWithEncryptionKey.createBackupWithEncryptionKey(databaseAdminClient, + projectId, + instanceId, databaseId, encryptedBackupId, key), new ShouldRetryBackupOperation()); assertThat(out).containsMatch(String.format( "Backup projects/%s/instances/%s/backups/%s of size \\d+ bytes " @@ -477,14 +542,14 @@ public void testEncryptedDatabaseAndBackupSamples() throws Exception { projectId, instanceId, encryptedBackupId, key)); out = SampleRunner.runSampleWithRetry( - () -> RestoreBackupWithEncryptionKey.restoreBackupWithEncryptionKey(dbClient, projectId, - instanceId, encryptedBackupId, encryptedRestoreId, key), + () -> RestoreBackupWithEncryptionKey.restoreBackupWithEncryptionKey(databaseAdminClient, + projectId, instanceId, encryptedBackupId, restoreId, key), new ShouldRetryBackupOperation()); assertThat(out).contains(String.format( "Database projects/%s/instances/%s/databases/%s" + " restored to projects/%s/instances/%s/databases/%s" + " from backup projects/%s/instances/%s/backups/%s" + " using encryption key %s", - projectId, instanceId, encryptedDatabaseId, projectId, instanceId, encryptedRestoreId, + projectId, instanceId, databaseId, projectId, instanceId, restoreId, projectId, instanceId, encryptedBackupId, key)); } finally { // Delete the backups from the test instance first, as the instance can only be deleted once @@ -494,13 +559,43 @@ public void testEncryptedDatabaseAndBackupSamples() throws Exception { } } + @Test + public void testDeleteBackups() { + try { + String projectId = spanner.getOptions().getProjectId(); + String databaseId = idGenerator.generateDatabaseId(); + String backupId = idGenerator.generateBackupId(); + + String out = SampleRunner + .runSample(() -> SpannerSample.createDatabase( + databaseAdminClient, InstanceName.of(projectId, instanceId), databaseId)); + assertThat(out).contains(String.format( + "Created database [%s]", DatabaseName.of(projectId, instanceId, databaseId))); + + out = SampleRunner.runSampleWithRetry( + () -> CreateBackupWithEncryptionKey.createBackupWithEncryptionKey(databaseAdminClient, + projectId, instanceId, databaseId, backupId, key), + new ShouldRetryBackupOperation()); + assertThat(out).containsMatch(String.format( + "Backup projects/%s/instances/%s/backups/%s of size \\d+ bytes " + + "was created at (.*) using encryption key %s", + projectId, instanceId, backupId, key)); + + out = runSample("deletebackup", databaseId, backupId); + assertThat(out).contains("Deleted backup [" + backupId + "]"); + } catch (Exception ex) { + Assert.fail("Exception raised => " + ex.getCause()); + } + } + private static void deleteAllBackups(String instanceId) throws InterruptedException { - for (Backup backup : dbClient.listBackups(instanceId).iterateAll()) { + InstanceName instanceName = InstanceName.of(projectId, instanceId); + for (Backup backup : databaseAdminClient.listBackups(instanceName.toString()).iterateAll()) { int attempts = 0; while (attempts < 30) { try { attempts++; - backup.delete(); + databaseAdminClient.deleteBackup(backup.getName()); break; } catch (SpannerException e) { if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION && e.getMessage() @@ -528,6 +623,9 @@ private String runSampleRunnable(Runnable sample) { @Test public void testCreateInstanceSample() { + String databaseId = idGenerator.generateDatabaseId(); + DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); + String instanceId = formatForTest("sample-inst"); String out = runSampleRunnable(() -> { @@ -567,6 +665,7 @@ static String formatForTest(String name) { } static class ShouldRetryBackupOperation implements Predicate { + private static final int MAX_ATTEMPTS = 20; private int attempts = 0; diff --git a/samples/snippets/src/test/java/com/example/spanner/SpannerStandaloneExamplesIT.java b/samples/snippets/src/test/java/com/example/spanner/SpannerStandaloneExamplesIT.java index 7c059bec1f..0acbf19893 100644 --- a/samples/snippets/src/test/java/com/example/spanner/SpannerStandaloneExamplesIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/SpannerStandaloneExamplesIT.java @@ -16,11 +16,20 @@ package com.example.spanner; +import static com.example.spanner.SpannerSampleIT.formatForTest; 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 com.example.spanner.CustomTimeoutAndRetrySettingsExample; +import com.example.spanner.QueryWithJsonParameterSample; +import com.example.spanner.QueryWithNumericParameterSample; +import com.example.spanner.StatementTimeoutExample; +import com.example.spanner.TransactionTimeoutExample; +import com.example.spanner.UpdateJsonDataSample; +import com.example.spanner.UpdateNumericDataSample; +import com.example.spanner.admin.archived.SpannerSampleIT; import com.google.api.gax.longrunning.OperationFuture; import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; @@ -56,7 +65,7 @@ public class SpannerStandaloneExamplesIT { // The instance needs to exist for tests to pass. private static String instanceId = System.getProperty("spanner.test.instance"); private static String baseDatabaseId = System.getProperty("spanner.sample.database", "mysample"); - private static String databaseId = SpannerSampleIT.formatForTest(baseDatabaseId); + private static String databaseId = formatForTest(baseDatabaseId); private static DatabaseId dbId; private static DatabaseAdminClient dbClient; private static Spanner spanner; @@ -183,7 +192,7 @@ public void addNumericColumn_shouldSuccessfullyAddColumn() () -> { try { AddNumericColumnSample.addNumericColumn( - spanner.getDatabaseAdminClient(), instanceId, databaseId); + spanner.getOptions().getProjectId(), instanceId, databaseId); } catch (ExecutionException e) { System.out.printf( "Adding column `Revenue` failed: %s%n", e.getCause().getMessage()); @@ -252,7 +261,7 @@ public void addJsonColumn_shouldSuccessfullyAddColumn() () -> { try { AddJsonColumnSample.addJsonColumn( - spanner.getDatabaseAdminClient(), instanceId, databaseId); + spanner.getOptions().getProjectId(), instanceId, databaseId); } catch (ExecutionException e) { System.out.printf( "Adding column `VenueDetails` failed: %s%n", e.getCause().getMessage()); diff --git a/samples/snippets/src/test/java/com/example/spanner/UpdateDatabaseSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/UpdateDatabaseSampleIT.java index 30ad8eec6a..b53414a2f5 100644 --- a/samples/snippets/src/test/java/com/example/spanner/UpdateDatabaseSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/UpdateDatabaseSampleIT.java @@ -20,40 +20,51 @@ import static org.junit.Assert.assertTrue; import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.DatabaseInfo.DatabaseField; +import com.google.common.collect.Lists; +import com.google.protobuf.FieldMask; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.DatabaseName; import com.google.spanner.admin.database.v1.UpdateDatabaseMetadata; -import java.util.Collections; +import com.google.spanner.admin.database.v1.UpdateDatabaseRequest; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class UpdateDatabaseSampleIT extends SampleTestBase { +public class UpdateDatabaseSampleIT extends SampleTestBaseV2 { @Test public void testUpdateDatabase() throws Exception { // Create database final String databaseId = idGenerator.generateDatabaseId(); databaseAdminClient - .createDatabase(instanceId, databaseId, Collections.emptyList()) + .createDatabaseAsync(getInstanceName(projectId, instanceId), + "CREATE DATABASE `" + databaseId + "`") .get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample( () -> UpdateDatabaseSample.updateDatabase(projectId, instanceId, databaseId)); - - DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); assertTrue( "Expected that database would have been updated. Output received was " + out, - out.contains(String.format("Updated database %s", dbId))); + out.contains(String.format( + "Updated database %s", DatabaseName.of(projectId, instanceId, databaseId)))); // Cleanup - Database databaseToUpdate = - databaseAdminClient.newDatabaseBuilder(dbId).disableDropProtection().build(); + final com.google.spanner.admin.database.v1.Database database = + com.google.spanner.admin.database.v1.Database.newBuilder() + .setName(DatabaseName.of(projectId, instanceId, databaseId).toString()) + .setEnableDropProtection(false).build(); + final UpdateDatabaseRequest updateDatabaseRequest = + UpdateDatabaseRequest.newBuilder() + .setDatabase(database) + .setUpdateMask( + FieldMask.newBuilder().addAllPaths( + Lists.newArrayList("enable_drop_protection")).build()) + .build(); + OperationFuture operation = - databaseAdminClient.updateDatabase(databaseToUpdate, DatabaseField.DROP_PROTECTION); + databaseAdminClient.updateDatabaseAsync(updateDatabaseRequest); Database updatedDb = operation.get(5, TimeUnit.MINUTES); - assertFalse(updatedDb.isDropProtectionEnabled()); + assertFalse(updatedDb.getEnableDropProtection()); } } diff --git a/samples/snippets/src/test/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSampleIT.java index ede90a5ec3..2953e02935 100644 --- a/samples/snippets/src/test/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/UpdateDatabaseWithDefaultLeaderSampleIT.java @@ -18,38 +18,35 @@ import static org.junit.Assert.assertTrue; -import com.google.cloud.spanner.Database; -import com.google.cloud.spanner.InstanceConfig; -import com.google.cloud.spanner.InstanceConfigId; -import java.util.Collections; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.instance.v1.InstanceConfig; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class UpdateDatabaseWithDefaultLeaderSampleIT extends SampleTestBase { +public class UpdateDatabaseWithDefaultLeaderSampleIT extends SampleTestBaseV2 { @Test public void testUpdateDatabaseWithDefaultLeader() throws Exception { // Create database final String databaseId = idGenerator.generateDatabaseId(); final Database createdDatabase = databaseAdminClient - .createDatabase(multiRegionalInstanceId, databaseId, Collections.emptyList()) + .createDatabaseAsync(getInstanceName(projectId, multiRegionalInstanceId), + "CREATE DATABASE `" + databaseId + "`") .get(5, TimeUnit.MINUTES); final String defaultLeader = createdDatabase.getDefaultLeader(); // Finds a possible new leader option - final InstanceConfigId instanceConfigId = instanceAdminClient - .getInstance(multiRegionalInstanceId) - .getInstanceConfigId(); - final InstanceConfig config = instanceAdminClient - .getInstanceConfig(instanceConfigId.getInstanceConfig()); - final String newLeader = config - .getLeaderOptions() - .stream() - .filter(leader -> !leader.equals(defaultLeader)) - .findFirst() - .orElseThrow(() -> - new RuntimeException("Expected to find a leader option different than " + defaultLeader) - ); + final String instanceConfigId = + instanceAdminClient.getInstance(getInstanceName(projectId, multiRegionalInstanceId)) + .getConfig(); + final InstanceConfig config = instanceAdminClient.getInstanceConfig(instanceConfigId); + final String newLeader = + config.getLeaderOptionsList().stream() + .filter(leader -> !leader.equals(defaultLeader)) + .findFirst().orElseThrow(() -> + new RuntimeException("Expected to find a leader option different than " + + defaultLeader) + ); // Runs sample final String out = SampleRunner.runSample(() -> UpdateDatabaseWithDefaultLeaderSample diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/AlterTableWithForeignKeyDeleteCascadeSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/AlterTableWithForeignKeyDeleteCascadeSampleIT.java similarity index 77% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/AlterTableWithForeignKeyDeleteCascadeSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/AlterTableWithForeignKeyDeleteCascadeSampleIT.java index 2295119b69..89c10cc460 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/AlterTableWithForeignKeyDeleteCascadeSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/AlterTableWithForeignKeyDeleteCascadeSampleIT.java @@ -14,31 +14,28 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; import com.example.spanner.SampleTestBase; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.DatabaseDialect; -import com.google.spanner.admin.database.v1.InstanceName; import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class AlterTableWithForeignKeyDeleteCascadeSampleIT extends SampleTestBaseV2 { +public class AlterTableWithForeignKeyDeleteCascadeSampleIT extends SampleTestBase { @Test public void testAlterTableWithForeignKeyDeleteCascade() throws Exception { // Creates database final String databaseId = idGenerator.generateDatabaseId(); - final CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setCreateStatement("CREATE DATABASE `" + databaseId + "`") - .setParent(InstanceName.of(projectId, instanceId).toString()) - .addAllExtraStatements(Arrays.asList( + databaseAdminClient + .createDatabase( + instanceId, + databaseId, + Arrays.asList( "CREATE TABLE Customers (\n" + " CustomerId INT64 NOT NULL,\n" + " CustomerName STRING(62) NOT NULL,\n" @@ -50,15 +47,15 @@ public void testAlterTableWithForeignKeyDeleteCascade() throws Exception { + " CONSTRAINT FKShoppingCartsCustomerId" + " FOREIGN KEY (CustomerId)\n" + " REFERENCES Customers (CustomerId)\n" - + " ) PRIMARY KEY (CartId)\n")).build(); - databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); + + " ) PRIMARY KEY (CartId)\n")) + .get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample( () -> AlterTableWithForeignKeyDeleteCascadeSample.alterForeignKeyDeleteCascadeConstraint( - projectId, instanceId, databaseId)); + databaseAdminClient, instanceId, databaseId)); assertTrue( "Expected to have created database " diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateDatabaseWithDefaultLeaderSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateDatabaseWithDefaultLeaderSampleIT.java new file mode 100644 index 0000000000..12b7c5044d --- /dev/null +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateDatabaseWithDefaultLeaderSampleIT.java @@ -0,0 +1,61 @@ +/* + * 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.example.spanner.admin.archived; + +import static org.junit.Assert.assertTrue; + +import com.example.spanner.SampleRunner; +import com.example.spanner.SampleTestBase; +import com.google.cloud.spanner.InstanceConfig; +import com.google.cloud.spanner.InstanceConfigId; +import org.junit.Test; + +public class CreateDatabaseWithDefaultLeaderSampleIT extends SampleTestBase { + + @Test + public void testCreateDatabaseWithDefaultLeader() throws Exception { + final String databaseId = idGenerator.generateDatabaseId(); + + // Finds possible default leader + final InstanceConfigId instanceConfigId = instanceAdminClient + .getInstance(multiRegionalInstanceId) + .getInstanceConfigId(); + final InstanceConfig config = instanceAdminClient + .getInstanceConfig(instanceConfigId.getInstanceConfig()); + assertTrue( + "Expected instance config " + instanceConfigId + " to have at least one leader option", + config.getLeaderOptions().size() > 0 + ); + final String defaultLeader = config.getLeaderOptions().get(0); + + // Runs sample + final String out = SampleRunner.runSample(() -> + CreateDatabaseWithDefaultLeaderSample.createDatabaseWithDefaultLeader( + projectId, + multiRegionalInstanceId, + databaseId, + defaultLeader + ) + ); + + assertTrue( + "Expected created database to have default leader " + defaultLeader + "." + + " Output received was " + out, + out.contains("Default leader: " + defaultLeader) + ); + } +} diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateDatabaseWithVersionRetentionPeriodSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateDatabaseWithVersionRetentionPeriodSampleIT.java similarity index 84% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateDatabaseWithVersionRetentionPeriodSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateDatabaseWithVersionRetentionPeriodSampleIT.java index 64400fbf21..448b1c10c4 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateDatabaseWithVersionRetentionPeriodSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateDatabaseWithVersionRetentionPeriodSampleIT.java @@ -14,20 +14,21 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static com.google.common.truth.Truth.assertThat; import com.example.spanner.SampleRunner; +import com.example.spanner.SampleTestBase; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** - * Integration tests for {@link com.example.spanner.CreateDatabaseWithVersionRetentionPeriodSample} + * Integration tests for {@link CreateDatabaseWithVersionRetentionPeriodSample} */ @RunWith(JUnit4.class) -public class CreateDatabaseWithVersionRetentionPeriodSampleIT extends SampleTestBaseV2 { +public class CreateDatabaseWithVersionRetentionPeriodSampleIT extends SampleTestBase { @Test public void createsDatabaseWithVersionRetentionPeriod() throws Exception { @@ -36,7 +37,7 @@ public void createsDatabaseWithVersionRetentionPeriod() throws Exception { final String out = SampleRunner.runSample(() -> CreateDatabaseWithVersionRetentionPeriodSample .createDatabaseWithVersionRetentionPeriod( - projectId, instanceId, databaseId, versionRetentionPeriod + databaseAdminClient, instanceId, databaseId, versionRetentionPeriod )); assertThat(out).contains( diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateInstanceWithAutoscalingConfigSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigSampleIT.java similarity index 58% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateInstanceWithAutoscalingConfigSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigSampleIT.java index 86224cfd30..041d0c5201 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateInstanceWithAutoscalingConfigSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigSampleIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 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. @@ -14,24 +14,31 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static com.google.common.truth.Truth.assertThat; import com.example.spanner.SampleRunner; -import com.google.spanner.admin.database.v1.InstanceName; +import com.example.spanner.SampleTestBase; +import com.google.cloud.spanner.InstanceId; +import java.util.UUID; import org.junit.Test; -public class CreateInstanceWithAutoscalingConfigSampleIT extends SampleTestBaseV2 { +public class CreateInstanceWithAutoscalingConfigSampleIT extends SampleTestBase { @Test public void testCreateInstanceWithAutoscalingConfig() throws Exception { - String instanceId = idGenerator.generateInstanceId(); + String instanceId = String.format("autoscaler-%s", UUID.randomUUID()); String out = SampleRunner.runSample( - () -> CreateInstanceWithAutoscalingConfigExample.createInstance(projectId, instanceId)); + () -> { + try { + CreateInstanceWithAutoscalingConfigExample.createInstance(projectId, instanceId); + } finally { + spanner.getInstanceAdminClient().deleteInstance(instanceId); + } + }); assertThat(out) - .contains(String.format("Autoscaler instance %s", - InstanceName.of(projectId, instanceId).toString())); + .contains(String.format("Autoscaler instance %s", InstanceId.of(projectId, instanceId))); } } diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateTableWithForeignKeyDeleteCascadeSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateTableWithForeignKeyDeleteCascadeSampleIT.java similarity index 71% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateTableWithForeignKeyDeleteCascadeSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateTableWithForeignKeyDeleteCascadeSampleIT.java index 6fd9aeddb1..a6cdee1947 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CreateTableWithForeignKeyDeleteCascadeSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CreateTableWithForeignKeyDeleteCascadeSampleIT.java @@ -14,37 +14,34 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; import com.example.spanner.SampleTestBase; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.InstanceName; import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class CreateTableWithForeignKeyDeleteCascadeSampleIT extends SampleTestBaseV2 { +public class CreateTableWithForeignKeyDeleteCascadeSampleIT extends SampleTestBase { @Test public void testCreateTableWithForeignKeyDeleteCascade() throws Exception { // Creates database final String databaseId = idGenerator.generateDatabaseId(); - final CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setCreateStatement("CREATE DATABASE `" + databaseId + "`") - .setParent(InstanceName.of(projectId, instanceId).toString()).build(); - databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); + databaseAdminClient + .createDatabase(instanceId, databaseId, Arrays.asList()) + .get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample( () -> CreateTableWithForeignKeyDeleteCascadeSample - .createForeignKeyDeleteCascadeConstraint(projectId, instanceId, databaseId)); + .createForeignKeyDeleteCascadeConstraint( + databaseAdminClient, instanceId, databaseId)); assertTrue( "Expected to have created database " diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CustomInstanceConfigSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CustomInstanceConfigSampleIT.java similarity index 64% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/CustomInstanceConfigSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/CustomInstanceConfigSampleIT.java index 8a01d2a7a6..a56b72b75f 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/CustomInstanceConfigSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/CustomInstanceConfigSampleIT.java @@ -1,11 +1,11 @@ /* - * Copyright 2024 Google LLC + * 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,17 +14,15 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; +import com.example.spanner.SampleTestBase; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -@RunWith(JUnit4.class) -public class CustomInstanceConfigSampleIT extends SampleTestBaseV2 { +public class CustomInstanceConfigSampleIT extends SampleTestBase { @Test public void testCustomInstanceConfigOperations() throws Exception { @@ -38,37 +36,26 @@ public void testCustomInstanceConfigOperations() throws Exception { projectId, instanceConfigName, customInstanceConfigId)); assertTrue(out1.contains("Created instance configuration")); - // Fetch the instance config that was created above. - final String out2 = - SampleRunner.runSample( - () -> GetInstanceConfigSample.getInstanceConfig(projectId, instanceConfigName)); - assertTrue(out2.contains("Available leader options for instance config")); - - // Fetch the instance config that was created above. - final String out3 = - SampleRunner.runSample( - () -> ListInstanceConfigsSample.listInstanceConfigs(projectId)); - assertTrue(out3.contains("Available leader options for instance config")); - // List the instance config operations. - final String out4 = + final String out2 = SampleRunner.runSample( () -> ListInstanceConfigOperationsSample.listInstanceConfigOperations(projectId)); - assertTrue(out4.contains("Obtained list of instance config operations")); + assertTrue(out2.contains("List instance config operation")); // Update display name to a randomly generated instance config id. - final String out5 = + final String out3 = SampleRunner.runSample( () -> - UpdateInstanceConfigSample.updateInstanceConfig(projectId, customInstanceConfigId)); - assertTrue(out5.contains("Updated instance configuration")); + UpdateInstanceConfigSample.updateInstanceConfig( + projectId, customInstanceConfigId)); + assertTrue(out3.contains("Updated instance configuration")); // Delete the created instance config. - final String out6 = + final String out4 = SampleRunner.runSample( () -> DeleteInstanceConfigSample.deleteInstanceConfig(projectId, customInstanceConfigId)); - assertTrue(out6.contains("Deleted instance configuration")); + assertTrue(out4.contains("Deleted instance configuration")); } } diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/DatabaseRolesIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/DatabaseRolesIT.java similarity index 82% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/DatabaseRolesIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/DatabaseRolesIT.java index 93b19a2b33..3e40189d94 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/DatabaseRolesIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/DatabaseRolesIT.java @@ -14,17 +14,17 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; +import com.example.spanner.SampleTestBase; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; -import com.google.common.collect.Lists; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.common.collect.ImmutableList; import java.util.Arrays; import java.util.Collections; import java.util.concurrent.TimeUnit; @@ -35,24 +35,20 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Integration tests for FGAC samples for GoogleStandardSql dialect. - */ +/** Integration tests for FGAC samples for GoogleStandardSql dialect. */ @RunWith(JUnit4.class) -public class DatabaseRolesIT extends SampleTestBaseV2 { +public class DatabaseRolesIT extends SampleTestBase { private static DatabaseId databaseId; @BeforeClass public static void createTestDatabase() throws Exception { final String database = idGenerator.generateDatabaseId(); - final CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setParent( - com.google.spanner.admin.database.v1.InstanceName.of(projectId, instanceId) - .toString()) - .setCreateStatement("CREATE DATABASE `" + database + "`") - .addAllExtraStatements(Lists.newArrayList( + databaseAdminClient + .createDatabase( + instanceId, + database, + ImmutableList.of( "CREATE TABLE Singers (" + " SingerId INT64 NOT NULL," + " FirstName STRING(1024)," @@ -67,8 +63,8 @@ public static void createTestDatabase() throws Exception { + " AlbumTitle STRING(MAX)," + " MarketingBudget INT64" + ") PRIMARY KEY (SingerId, AlbumId)," - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).build(); - databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")) + .get(10, TimeUnit.MINUTES); databaseId = DatabaseId.of(projectId, instanceId, database); } @@ -109,7 +105,7 @@ public void testAddAndDropDatabaseRole() throws Exception { SampleRunner.runSample( () -> AddAndDropDatabaseRole.addAndDropDatabaseRole( - projectId, instanceId, databaseId.getDatabase(), "new_parent", "new_child")); + projectId, instanceId, databaseId.getDatabase(), "new-parent", "new-child")); assertTrue(out.contains("Created roles new_parent and new_child and granted privileges")); assertTrue(out.contains("Revoked privileges and dropped role new_child")); } @@ -121,6 +117,6 @@ public void testListDatabaseRoles() throws Exception { () -> ListDatabaseRoles.listDatabaseRoles( projectId, instanceId, databaseId.getDatabase())); - assertTrue(out.contains("Obtained role ")); + assertTrue(out.contains("new_parent")); } } diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/DropForeignKeyConstraintDeleteCascadeSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/DropForeignKeyConstraintDeleteCascadeSampleIT.java similarity index 77% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/DropForeignKeyConstraintDeleteCascadeSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/DropForeignKeyConstraintDeleteCascadeSampleIT.java index f2dae05237..a4ce31c9d8 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/DropForeignKeyConstraintDeleteCascadeSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/DropForeignKeyConstraintDeleteCascadeSampleIT.java @@ -14,31 +14,28 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; import com.example.spanner.SampleTestBase; -import com.google.common.collect.Lists; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.InstanceName; import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class DropForeignKeyConstraintDeleteCascadeSampleIT extends SampleTestBaseV2 { +public class DropForeignKeyConstraintDeleteCascadeSampleIT extends SampleTestBase { @Test public void testDropForeignKeyConstraintDeleteCascade() throws Exception { // Creates database final String databaseId = idGenerator.generateDatabaseId(); - final CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setCreateStatement("CREATE DATABASE `" + databaseId + "`") - .setParent(InstanceName.of(projectId, instanceId).toString()) - .addAllExtraStatements(Lists.newArrayList( + databaseAdminClient + .createDatabase( + instanceId, + databaseId, + Arrays.asList( "CREATE TABLE Customers (\n" + " CustomerId INT64 NOT NULL,\n" + " CustomerName STRING(62) NOT NULL,\n" @@ -50,15 +47,15 @@ public void testDropForeignKeyConstraintDeleteCascade() throws Exception { + " CONSTRAINT FKShoppingCartsCustomerName" + " FOREIGN KEY (CustomerName)\n" + " REFERENCES Customers (CustomerName) ON DELETE CASCADE\n" - + " ) PRIMARY KEY (CartId)\n")).build(); - databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); + + " ) PRIMARY KEY (CartId)\n")) + .get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample( () -> DropForeignKeyConstraintDeleteCascadeSample.deleteForeignKeyDeleteCascadeConstraint( - projectId, instanceId, databaseId)); + databaseAdminClient, instanceId, databaseId)); assertTrue( "Expected to have dropped foreign-key constraints from tables in created database " diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/EncryptionKeyIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/EncryptionKeyIT.java similarity index 85% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/EncryptionKeyIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/EncryptionKeyIT.java index 5b2513d91c..ffd0771fa0 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/EncryptionKeyIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/EncryptionKeyIT.java @@ -14,18 +14,17 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static com.google.common.truth.Truth.assertThat; import com.example.spanner.SampleRunner; +import com.example.spanner.SampleTestBase; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Uninterruptibles; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.spanner.admin.database.v1.InstanceName; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import org.junit.BeforeClass; @@ -35,13 +34,12 @@ import org.junit.runners.JUnit4; /** - * Integration tests for: {@link com.example.spanner.CreateDatabaseWithEncryptionKey}, - * {@link com.example.spanner.CreateBackupWithEncryptionKey} and - * {@link com.example.spanner.RestoreBackupWithEncryptionKey} + * Integration tests for: {@link CreateDatabaseWithEncryptionKey}, {@link + * CreateBackupWithEncryptionKey} and {@link RestoreBackupWithEncryptionKey} */ @RunWith(JUnit4.class) @Ignore -public class EncryptionKeyIT extends SampleTestBaseV2 { +public class EncryptionKeyIT extends SampleTestBase { private static String key; @@ -62,10 +60,16 @@ public void testEncryptedDatabaseAndBackupAndRestore() throws Exception { final String restoreId = idGenerator.generateDatabaseId(); String out = SampleRunner.runSample(() -> - SpannerSample.createDatabase( - databaseAdminClient, InstanceName.of(projectId, instanceId), databaseId)); - assertThat(out).contains(String.format( - "Created database [%s]", DatabaseName.of(projectId, instanceId, databaseId))); + CreateDatabaseWithEncryptionKey.createDatabaseWithEncryptionKey( + databaseAdminClient, + projectId, + instanceId, + databaseId, + key + )); + assertThat(out).contains( + "Database projects/" + projectId + "/instances/" + instanceId + "/databases/" + databaseId + + " created with encryption key " + key); out = SampleRunner.runSampleWithRetry(() -> CreateBackupWithEncryptionKey.createBackupWithEncryptionKey( diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/GetDatabaseDdlSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/GetDatabaseDdlSampleIT.java similarity index 56% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/GetDatabaseDdlSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/GetDatabaseDdlSampleIT.java index 8769a12598..404aceca72 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/GetDatabaseDdlSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/GetDatabaseDdlSampleIT.java @@ -14,49 +14,48 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; -import com.google.common.collect.Lists; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.instance.v1.InstanceConfig; -import com.google.spanner.admin.instance.v1.InstanceName; +import com.example.spanner.SampleTestBase; +import com.google.cloud.spanner.InstanceConfig; +import com.google.cloud.spanner.InstanceConfigId; +import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class GetDatabaseDdlSampleIT extends SampleTestBaseV2 { +public class GetDatabaseDdlSampleIT extends SampleTestBase { @Test public void testGetDatabaseDdl() throws Exception { // Finds a possible new leader option - final String instanceConfigId = instanceAdminClient.getInstance( - InstanceName.of(projectId, multiRegionalInstanceId)).getConfig(); - final InstanceConfig config = instanceAdminClient.getInstanceConfig(instanceConfigId); + final InstanceConfigId instanceConfigId = instanceAdminClient + .getInstance(multiRegionalInstanceId) + .getInstanceConfigId(); + final InstanceConfig config = instanceAdminClient + .getInstanceConfig(instanceConfigId.getInstanceConfig()); assertTrue( "Expected instance config " + instanceConfigId + " to have at least one leader option", - config.getLeaderOptionsList().size() > 0 + config.getLeaderOptions().size() > 0 ); - final String defaultLeader = config.getLeaderOptions(0); + final String defaultLeader = config.getLeaderOptions().get(0); // Creates database final String databaseId = idGenerator.generateDatabaseId(); - final CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setParent( - com.google.spanner.admin.database.v1.InstanceName.of(projectId, - multiRegionalInstanceId).toString()) - .setCreateStatement("CREATE DATABASE `" + databaseId + "`") - .addAllExtraStatements(Lists.newArrayList( - "CREATE TABLE Singers (Id INT64 NOT NULL) PRIMARY KEY (Id)", - "ALTER DATABASE `" - + databaseId - + "` SET OPTIONS ( default_leader = '" - + defaultLeader - + "')" - )).build(); - databaseAdminClient.createDatabaseAsync(request).get(5, TimeUnit.MINUTES); + databaseAdminClient.createDatabase( + multiRegionalInstanceId, + databaseId, + Arrays.asList( + "CREATE TABLE Singers (Id INT64 NOT NULL) PRIMARY KEY (Id)", + "ALTER DATABASE `" + + databaseId + + "` SET OPTIONS ( default_leader = '" + + defaultLeader + + "')" + ) + ).get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample(() -> GetDatabaseDdlSample diff --git a/samples/snippets/src/test/java/com/example/spanner/GetInstanceConfigSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/GetInstanceConfigSampleIT.java similarity index 90% rename from samples/snippets/src/test/java/com/example/spanner/GetInstanceConfigSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/GetInstanceConfigSampleIT.java index 2690093de8..ac3598f549 100644 --- a/samples/snippets/src/test/java/com/example/spanner/GetInstanceConfigSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/GetInstanceConfigSampleIT.java @@ -14,10 +14,12 @@ * limitations under the License. */ -package com.example.spanner; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; +import com.example.spanner.SampleRunner; +import com.example.spanner.SampleTestBase; import org.junit.Test; public class GetInstanceConfigSampleIT extends SampleTestBase { diff --git a/samples/snippets/src/test/java/com/example/spanner/ListInstanceConfigsSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/ListInstanceConfigsSampleIT.java similarity index 89% rename from samples/snippets/src/test/java/com/example/spanner/ListInstanceConfigsSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/ListInstanceConfigsSampleIT.java index ef2b730cd3..8dcee20313 100644 --- a/samples/snippets/src/test/java/com/example/spanner/ListInstanceConfigsSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/ListInstanceConfigsSampleIT.java @@ -14,10 +14,12 @@ * limitations under the License. */ -package com.example.spanner; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; +import com.example.spanner.SampleRunner; +import com.example.spanner.SampleTestBase; import org.junit.Test; public class ListInstanceConfigsSampleIT extends SampleTestBase { diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/PgCaseSensitivitySampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/PgCaseSensitivitySampleIT.java similarity index 62% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/PgCaseSensitivitySampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/PgCaseSensitivitySampleIT.java index 88337ba8c6..100014643d 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/PgCaseSensitivitySampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/PgCaseSensitivitySampleIT.java @@ -14,27 +14,30 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.DatabaseDialect; -import com.google.spanner.admin.database.v1.InstanceName; +import com.example.spanner.SampleTestBase; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import java.util.Collections; import org.junit.Test; -public class PgCaseSensitivitySampleIT extends SampleTestBaseV2 { +public class PgCaseSensitivitySampleIT extends SampleTestBase { @Test public void testPgCaseSensitivitySample() throws Exception { final String databaseId = idGenerator.generateDatabaseId(); - final CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setCreateStatement(getCreateDatabaseStatement(databaseId, DatabaseDialect.POSTGRESQL)) - .setParent(InstanceName.of(projectId, instanceId).toString()) - .setDatabaseDialect(DatabaseDialect.POSTGRESQL).build(); - databaseAdminClient.createDatabaseAsync(request).get(); + databaseAdminClient + .createDatabase( + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.POSTGRESQL) + .build(), + Collections.emptyList()) + .get(); final String out = SampleRunner.runSample( diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/PgInterleavedTableSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/PgInterleavedTableSampleIT.java similarity index 61% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/PgInterleavedTableSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/PgInterleavedTableSampleIT.java index 59a0f4a524..b7d229a1b8 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/PgInterleavedTableSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/PgInterleavedTableSampleIT.java @@ -14,27 +14,30 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.DatabaseDialect; -import com.google.spanner.admin.database.v1.InstanceName; +import com.example.spanner.SampleTestBase; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import java.util.Collections; import org.junit.Test; -public class PgInterleavedTableSampleIT extends SampleTestBaseV2 { +public class PgInterleavedTableSampleIT extends SampleTestBase { @Test public void testPgInterleavedTableSample() throws Exception { final String databaseId = idGenerator.generateDatabaseId(); - final CreateDatabaseRequest request = - CreateDatabaseRequest.newBuilder() - .setCreateStatement(getCreateDatabaseStatement(databaseId, DatabaseDialect.POSTGRESQL)) - .setParent(InstanceName.of(projectId, instanceId).toString()) - .setDatabaseDialect(DatabaseDialect.POSTGRESQL).build(); - databaseAdminClient.createDatabaseAsync(request).get(); + databaseAdminClient + .createDatabase( + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.POSTGRESQL) + .build(), + Collections.emptyList()) + .get(); final String out = SampleRunner.runSample( diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/PgSpannerSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/PgSpannerSampleIT.java similarity index 84% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/PgSpannerSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/PgSpannerSampleIT.java index 90885b71ce..72900b5e41 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/PgSpannerSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/PgSpannerSampleIT.java @@ -14,23 +14,22 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static com.google.common.truth.Truth.assertThat; import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.spanner.admin.database.v1.InstanceName; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.PrintStream; +import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -41,23 +40,26 @@ */ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") -public class PgSpannerSampleIT extends SampleTestBaseV2 { - +public class PgSpannerSampleIT { private static final int DBID_LENGTH = 20; // The instance needs to exist for tests to pass. private static final String instanceId = System.getProperty("spanner.test.instance"); private static final String baseDbId = System.getProperty("spanner.sample.database"); + private static final String databaseId = formatForTest(baseDbId); + private static final String encryptedDatabaseId = formatForTest(baseDbId); + private static final String encryptedBackupId = formatForTest(baseDbId); + private static final String encryptedRestoreId = formatForTest(baseDbId); static Spanner spanner; static DatabaseId dbId; static DatabaseAdminClient dbClient; @BeforeClass - public static void setUp() throws IOException { + public static void setUp() { SpannerOptions options = SpannerOptions.newBuilder().setAutoThrottleAdministrativeRequests().build(); spanner = options.getService(); - dbClient = DatabaseAdminClient.create(); - dbId = DatabaseId.of(options.getProjectId(), instanceId, idGenerator.generateDatabaseId()); + dbClient = spanner.getDatabaseAdminClient(); + dbId = DatabaseId.of(options.getProjectId(), instanceId, databaseId); // Delete stale test databases that have been created earlier by this test, but not deleted. deleteStaleTestDatabases(); } @@ -66,25 +68,34 @@ static void deleteStaleTestDatabases() { Timestamp now = Timestamp.now(); Pattern samplePattern = getTestDbIdPattern(PgSpannerSampleIT.baseDbId); Pattern restoredPattern = getTestDbIdPattern("restored"); - for (Database db : dbClient.listDatabases( - InstanceName.of(projectId, instanceId)).iterateAll()) { - DatabaseName databaseName = DatabaseName.parse(db.getName()); + for (Database db : dbClient.listDatabases(PgSpannerSampleIT.instanceId).iterateAll()) { if (TimeUnit.HOURS.convert(now.getSeconds() - db.getCreateTime().getSeconds(), TimeUnit.SECONDS) > 24) { - if (databaseName.getDatabase().length() >= DBID_LENGTH) { - if (samplePattern.matcher( - toComparableId(PgSpannerSampleIT.baseDbId, databaseName.getDatabase())).matches()) { - dbClient.dropDatabase(db.getName()); + if (db.getId().getDatabase().length() >= DBID_LENGTH) { + if (samplePattern.matcher(toComparableId(PgSpannerSampleIT.baseDbId, + db.getId().getDatabase())).matches()) { + db.drop(); } - if (restoredPattern.matcher(toComparableId("restored", databaseName.getDatabase())) + if (restoredPattern.matcher(toComparableId("restored", db.getId().getDatabase())) .matches()) { - dbClient.dropDatabase(db.getName()); + db.drop(); } } } } } + @AfterClass + public static void tearDown() { + dbClient.dropDatabase(dbId.getInstanceId().getInstance(), dbId.getDatabase()); + dbClient.dropDatabase( + dbId.getInstanceId().getInstance(), SpannerSample.createRestoredSampleDbId(dbId)); + dbClient.dropDatabase(instanceId, encryptedDatabaseId); + dbClient.dropDatabase(instanceId, encryptedRestoreId); + dbClient.deleteBackup(instanceId, encryptedBackupId); + spanner.close(); + } + private static String toComparableId(String baseId, String existingId) { String zeroUuid = "00000000-0000-0000-0000-0000-00000000"; int shouldBeLength = (baseId + "-" + zeroUuid).length(); @@ -98,13 +109,17 @@ private static Pattern getTestDbIdPattern(String baseDbId) { Pattern.CASE_INSENSITIVE); } - private String runSample(String command) throws Exception { + static String formatForTest(String name) { + return name + "-" + UUID.randomUUID().toString().substring(0, DBID_LENGTH); + } + + private String runSample(String command) { final PrintStream stdOut = System.out; final ByteArrayOutputStream bout = new ByteArrayOutputStream(); final PrintStream out = new PrintStream(bout); System.setOut(out); - System.out.println(instanceId + ":" + dbId.getDatabase()); - PgSpannerSample.main(new String[]{command, instanceId, dbId.getDatabase()}); + System.out.println(instanceId + ":" + databaseId); + PgSpannerSample.main(new String[]{command, instanceId, databaseId}); System.setOut(stdOut); return bout.toString(); } @@ -112,7 +127,7 @@ private String runSample(String command) throws Exception { @Test public void testSample() throws Exception { assertThat(instanceId).isNotNull(); - assertThat(dbId.getDatabase()).isNotNull(); + assertThat(databaseId).isNotNull(); System.out.println("Create Database ..."); String out = runSample("createpgdatabase"); diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/SequenceSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/SequenceSampleIT.java similarity index 69% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/SequenceSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/SequenceSampleIT.java index b3f4df004d..e1e527042a 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/SequenceSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/SequenceSampleIT.java @@ -14,15 +14,17 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static com.example.spanner.SampleRunner.runSample; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import com.example.spanner.SampleTestBase; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; import com.google.common.collect.ImmutableList; -import com.google.spanner.admin.database.v1.CreateDatabaseRequest; -import com.google.spanner.admin.database.v1.DatabaseDialect; +import java.util.Collections; import java.util.HashSet; import java.util.concurrent.TimeUnit; import org.junit.Before; @@ -37,23 +39,23 @@ * dialects. */ @RunWith(Parameterized.class) -public class SequenceSampleIT extends SampleTestBaseV2 { +public class SequenceSampleIT extends SampleTestBase { - private static String databaseId; + private static DatabaseId databaseId; /** * Set of dialects for which database has already been created in this test suite. This helps in * limiting the number of databases created per dialect to one. */ - private static final HashSet dbInitializedDialects = new HashSet<>(); + private static final HashSet dbInitializedDialects = new HashSet<>(); @Parameters(name = "dialect = {0}") - public static Iterable data() { - return ImmutableList.of(DatabaseDialect.GOOGLE_STANDARD_SQL, DatabaseDialect.POSTGRESQL); + public static Iterable data() { + return ImmutableList.of(Dialect.GOOGLE_STANDARD_SQL, Dialect.POSTGRESQL); } @Parameter(0) - public static DatabaseDialect dialect; + public static Dialect dialect; @Before public void createTestDatabase() throws Exception { @@ -62,36 +64,37 @@ public void createTestDatabase() throws Exception { return; } dbInitializedDialects.add(dialect); - databaseId = idGenerator.generateDatabaseId(); - CreateDatabaseRequest createDatabaseRequest = - CreateDatabaseRequest.newBuilder() - .setParent(getInstanceName(projectId, instanceId)) - .setCreateStatement(getCreateDatabaseStatement(databaseId, dialect)) - .setDatabaseDialect(dialect).build(); + final String database = idGenerator.generateDatabaseId(); databaseAdminClient - .createDatabaseAsync(createDatabaseRequest) + .createDatabase( + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, database)) + .setDialect(dialect) + .build(), + Collections.emptyList()) .get(10, TimeUnit.MINUTES); + databaseId = DatabaseId.of(projectId, instanceId, database); } @Test public void createSequence() throws Exception { String out; - if (dialect == DatabaseDialect.GOOGLE_STANDARD_SQL) { + if (dialect == Dialect.GOOGLE_STANDARD_SQL) { out = runSample( () -> CreateSequenceSample.createSequence( - projectId, instanceId, databaseId)); + projectId, instanceId, databaseId.getDatabase())); } else { out = runSample( () -> PgCreateSequenceSample.pgCreateSequence( - projectId, instanceId, databaseId)); + projectId, instanceId, databaseId.getDatabase())); } assertTrue( out.contains( - "Created Seq sequence and Customers table, where the key column " + "Created Seq sequence and Customers table, where its key column " + "CustomerId uses the sequence as a default value")); assertEquals(out.split("Inserted customer record with CustomerId", -1).length - 1, 3); assertTrue(out.contains("Number of customer records inserted is: 3")); @@ -100,18 +103,18 @@ public void createSequence() throws Exception { @Test public void alterSequence() throws Exception { String out; - if (dialect == DatabaseDialect.GOOGLE_STANDARD_SQL) { + if (dialect == Dialect.GOOGLE_STANDARD_SQL) { out = runSample( () -> AlterSequenceSample.alterSequence( - projectId, instanceId, databaseId)); + projectId, instanceId, databaseId.getDatabase())); } else { out = runSample( () -> PgAlterSequenceSample.pgAlterSequence( - projectId, instanceId, databaseId)); + projectId, instanceId, databaseId.getDatabase())); } assertTrue( out.contains("Altered Seq sequence to skip an inclusive range between 1000 and 5000000")); @@ -122,17 +125,17 @@ public void alterSequence() throws Exception { @Test public void dropSequence() throws Exception { String out; - if (dialect == DatabaseDialect.GOOGLE_STANDARD_SQL) { + if (dialect == Dialect.GOOGLE_STANDARD_SQL) { out = runSample( () -> - DropSequenceSample.dropSequence(projectId, instanceId, databaseId)); + DropSequenceSample.dropSequence(projectId, instanceId, databaseId.getDatabase())); } else { out = runSample( () -> PgDropSequenceSample.pgDropSequence( - projectId, instanceId, databaseId)); + projectId, instanceId, databaseId.getDatabase())); } assertTrue( out.contains( diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/archived/SpannerSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/SpannerSampleIT.java new file mode 100644 index 0000000000..66410cce4d --- /dev/null +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/SpannerSampleIT.java @@ -0,0 +1,593 @@ +/* + * Copyright 2017 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.archived; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertTrue; + +import com.example.spanner.SampleRunner; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Backup; +import com.google.cloud.spanner.BackupId; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Instance; +import com.google.cloud.spanner.InstanceAdminClient; +import com.google.cloud.spanner.InstanceConfigId; +import com.google.cloud.spanner.InstanceId; +import com.google.cloud.spanner.InstanceInfo; +import com.google.cloud.spanner.Options; +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.base.Preconditions; +import com.google.common.util.concurrent.Uninterruptibles; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.threeten.bp.LocalDate; +import org.threeten.bp.temporal.ChronoField; + +/** Unit tests for {@code SpannerSample} */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class SpannerSampleIT { + private static final int DBID_LENGTH = 20; + // The instance needs to exist for tests to pass. + private static final String instanceId = System.getProperty("spanner.test.instance"); + private static final String baseDbId = System.getProperty("spanner.sample.database"); + private static final String keyLocation = + Preconditions.checkNotNull(System.getProperty("spanner.test.key.location")); + private static final String keyRing = + Preconditions.checkNotNull(System.getProperty("spanner.test.key.ring")); + private static final String keyName = + Preconditions.checkNotNull(System.getProperty("spanner.test.key.name")); + private static final String databaseId = formatForTest(baseDbId); + private static final String encryptedDatabaseId = formatForTest(baseDbId); + private static final String encryptedBackupId = formatForTest(baseDbId); + private static final String encryptedRestoreId = formatForTest(baseDbId); + private static final long STALE_INSTANCE_THRESHOLD_SECS = + TimeUnit.SECONDS.convert(24L, TimeUnit.HOURS); + static Spanner spanner; + static DatabaseId dbId; + static DatabaseAdminClient dbClient; + private static String key; + private long lastUpdateDataTimeInMillis; + + private String runSample(String command) throws Exception { + PrintStream stdOut = System.out; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(bout); + System.setOut(out); + SpannerSample.main(new String[] {command, instanceId, databaseId}); + System.setOut(stdOut); + return bout.toString(); + } + + @BeforeClass + public static void setUp() throws Exception { + SpannerOptions options = + SpannerOptions.newBuilder().setAutoThrottleAdministrativeRequests().build(); + spanner = options.getService(); + dbClient = spanner.getDatabaseAdminClient(); + dbId = DatabaseId.of(options.getProjectId(), instanceId, databaseId); + // Delete stale test databases that have been created earlier by this test, but not deleted. + deleteStaleTestDatabases(instanceId, baseDbId); + key = + String.format( + "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", + options.getProjectId(), keyLocation, keyRing, keyName); + + /* + * Delete stale instances that have been created earlier by this test but not deleted. + * Backups needed to be deleted from the instance first, as the instance can only be + * deleted once all backups have been deleted. + * */ + deleteStaleEncryptedTestInstances(); + } + + /** + * Deleting all the test instances with name starting with 'encrypted-test-' and were created + * before 24 hours. + * + * @throws InterruptedException If Thread.sleep() interrupted + */ + private static void deleteStaleEncryptedTestInstances() throws InterruptedException { + Timestamp now = Timestamp.now(); + + for (Instance instance : + spanner + .getInstanceAdminClient() + .listInstances(Options.filter("name:encrypted-test-")) + .iterateAll()) { + if ((now.getSeconds() - instance.getCreateTime().getSeconds()) + > STALE_INSTANCE_THRESHOLD_SECS) { + deleteAllBackups(instance.getId().getInstance()); + instance.delete(); + } + } + } + + static void deleteStaleTestDatabases(String instanceId, String baseDbId) { + Timestamp now = Timestamp.now(); + Pattern samplePattern = getTestDbIdPattern(baseDbId); + Pattern restoredPattern = getTestDbIdPattern("restored"); + for (Database db : dbClient.listDatabases(instanceId).iterateAll()) { + if (TimeUnit.HOURS.convert(now.getSeconds() - db.getCreateTime().getSeconds(), + TimeUnit.SECONDS) > 24) { + if (db.getId().getDatabase().length() >= DBID_LENGTH) { + if (samplePattern.matcher(toComparableId(baseDbId, db.getId().getDatabase())).matches()) { + db.drop(); + } + if (restoredPattern.matcher(toComparableId("restored", db.getId().getDatabase())) + .matches()) { + db.drop(); + } + } + } + } + } + + @AfterClass + public static void tearDown() throws Exception { + dbClient.dropDatabase(dbId.getInstanceId().getInstance(), dbId.getDatabase()); + dbClient.dropDatabase( + dbId.getInstanceId().getInstance(), SpannerSample.createRestoredSampleDbId(dbId)); + dbClient.dropDatabase(instanceId, encryptedDatabaseId); + dbClient.dropDatabase(instanceId, encryptedRestoreId); + dbClient.deleteBackup(instanceId, encryptedBackupId); + spanner.close(); + } + + @Test + public void testSample() throws Exception { + assertThat(instanceId).isNotNull(); + assertThat(databaseId).isNotNull(); + String out = runSample("createdatabase"); + assertThat(out).contains("Created database"); + assertThat(out).contains(dbId.getName()); + + runSample("write"); + + out = runSample("delete"); + assertThat(out).contains("Records deleted."); + + runSample("write"); + + out = runSample("read"); + assertThat(out).contains("1 1 Total Junk"); + + out = runSample("query"); + assertThat(out).contains("1 1 Total Junk"); + runSample("addmarketingbudget"); + + // wait for 15 seconds to elapse and then run an update, and query for stale data + lastUpdateDataTimeInMillis = System.currentTimeMillis(); + while (System.currentTimeMillis() < lastUpdateDataTimeInMillis + 16000) { + Thread.sleep(1000); + } + runSample("update"); + out = runSample("readstaledata"); + assertThat(out).contains("1 1 NULL"); + runSample("writetransaction"); + out = runSample("querymarketingbudget"); + assertThat(out).contains("1 1 300000"); + assertThat(out).contains("2 2 300000"); + + runSample("addindex"); + out = runSample("queryindex"); + assertThat(out).contains("Go, Go, Go"); + assertThat(out).contains("Forever Hold Your Peace"); + assertThat(out).doesNotContain("Green"); + + out = runSample("readindex"); + assertThat(out).contains("Go, Go, Go"); + assertThat(out).contains("Forever Hold Your Peace"); + assertThat(out).contains("Green"); + + runSample("addstoringindex"); + out = runSample("readstoringindex"); + assertThat(out).contains("300000"); + + out = runSample("readonlytransaction"); + assertThat(out.replaceAll("[\r\n]+", " ")).containsMatch("(Total Junk.*){2}"); + + out = runSample("addcommittimestamp"); + assertThat(out).contains("Added LastUpdateTime as a commit timestamp column"); + + runSample("updatewithtimestamp"); + out = runSample("querywithtimestamp"); + assertThat(out).contains("1 1 1000000"); + assertThat(out).contains("2 2 750000"); + + out = runSample("createtablewithtimestamp"); + assertThat(out).contains("Created Performances table in database"); + + runSample("writewithtimestamp"); + out = runSample("queryperformancestable"); + assertThat(out).contains("1 4 2017-10-05 11000"); + assertThat(out).contains("1 19 2017-11-02 15000"); + assertThat(out).contains("2 42 2017-12-23 7000"); + + runSample("writestructdata"); + out = runSample("querywithstruct"); + assertThat(out).startsWith("6\n"); + + out = runSample("querywitharrayofstruct"); + assertThat(out).startsWith("8\n7\n6"); + + out = runSample("querystructfield"); + assertThat(out).startsWith("6\n"); + + out = runSample("querynestedstructfield"); + assertThat(out).contains("6 Imagination\n"); + assertThat(out).contains("9 Imagination\n"); + + runSample("insertusingdml"); + out = runSample("querysingerstable"); + assertThat(out).contains("Virginia Watson"); + + runSample("updateusingdml"); + out = runSample("querymarketingbudget"); + assertThat(out).contains("1 1 2000000"); + + runSample("deleteusingdml"); + out = runSample("querysingerstable"); + assertThat(out).doesNotContain("Alice Trentor"); + + out = runSample("updateusingdmlwithtimestamp"); + assertThat(out).contains("2 records updated"); + + out = runSample("writeandreadusingdml"); + assertThat(out).contains("Timothy Campbell"); + + runSample("updateusingdmlwithstruct"); + out = runSample("querysingerstable"); + assertThat(out).contains("Timothy Grant"); + + runSample("writeusingdml"); + out = runSample("querysingerstable"); + assertThat(out).contains("Melissa Garcia"); + assertThat(out).contains("Russell Morales"); + assertThat(out).contains("Jacqueline Long"); + assertThat(out).contains("Dylan Shaw"); + out = runSample("querywithparameter"); + assertThat(out).contains("12 Melissa Garcia"); + + runSample("writewithtransactionusingdml"); + out = runSample("querymarketingbudget"); + assertThat(out).contains("1 1 2200000"); + assertThat(out).contains("2 2 550000"); + + runSample("updateusingpartitioneddml"); + out = runSample("querymarketingbudget"); + assertThat(out).contains("1 1 2200000"); + assertThat(out).contains("2 2 100000"); + + runSample("deleteusingpartitioneddml"); + out = runSample("querysingerstable"); + assertThat(out).doesNotContain("Timothy Grant"); + assertThat(out).doesNotContain("Melissa Garcia"); + assertThat(out).doesNotContain("Russell Morales"); + assertThat(out).doesNotContain("Jacqueline Long"); + assertThat(out).doesNotContain("Dylan Shaw"); + + out = runSample("updateusingbatchdml"); + assertThat(out).contains("1 record updated by stmt 0"); + assertThat(out).contains("1 record updated by stmt 1"); + + out = runSample("createtablewithdatatypes"); + assertThat(out).contains("Created Venues table in database"); + + runSample("writedatatypesdata"); + out = runSample("querywitharray"); + assertThat(out).contains("19 Venue 19 2020-11-01"); + assertThat(out).contains("42 Venue 42 2020-10-01"); + + out = runSample("querywithbool"); + assertThat(out).contains("19 Venue 19 true"); + + out = runSample("querywithbytes"); + assertThat(out).contains("4 Venue 4"); + + out = runSample("querywithdate"); + assertThat(out).contains("4 Venue 4 2018-09-02"); + assertThat(out).contains("42 Venue 42 2018-10-01"); + + out = runSample("querywithfloat"); + assertThat(out).contains("4 Venue 4 0.8"); + assertThat(out).contains("19 Venue 19 0.9"); + + out = runSample("querywithint"); + assertThat(out).contains("19 Venue 19 6300"); + assertThat(out).contains("42 Venue 42 3000"); + + out = runSample("querywithstring"); + assertThat(out).contains("42 Venue 42"); + + out = runSample("querywithtimestampparameter"); + assertThat(out).contains("4 Venue 4"); + assertThat(out).contains("19 Venue 19"); + assertThat(out).contains("42 Venue 42"); + + out = runSample("querywithnumeric"); + assertThat(out).contains("19 Venue 19 1200100"); + assertThat(out).contains("42 Venue 42 390650.99"); + + out = runSample("clientwithqueryoptions"); + assertThat(out).contains("1 1 Total Junk"); + out = runSample("querywithqueryoptions"); + assertThat(out).contains("1 1 Total Junk"); + + String backupName = + String.format( + "%s_%02d", + dbId.getDatabase(), LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR)); + BackupId backupId = BackupId.of(dbId.getInstanceId(), backupName); + + out = runSample("createbackup"); + assertThat(out).contains("Created backup [" + backupId + "]"); + + out = runSample("cancelcreatebackup"); + assertThat(out).contains( + "Backup operation for [" + backupId + "_cancel] successfully"); + + // TODO: remove try-catch when filtering on metadata fields works. + try { + out = runSample("listbackupoperations"); + assertThat(out).contains( + String.format( + "Backup %s on database %s pending:", + backupId.getName(), + dbId.getName())); + assertTrue("Out does not contain copy backup operations", out.contains( + "Copy Backup Operations")); + } catch (SpannerException e) { + assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT); + assertThat(e.getMessage()).contains("Cannot evaluate filter expression"); + } + + out = runSample("listbackups"); + assertThat(out).contains("All backups:"); + assertThat(out).contains( + String.format("All backups with backup name containing \"%s\":", backupId.getBackup())); + assertThat(out).contains(String.format( + "All backups for databases with a name containing \"%s\":", + dbId.getDatabase())); + assertThat(out).contains( + String.format("All backups that expire before")); + assertThat(out).contains("All backups with size greater than 100 bytes:"); + assertThat(out).containsMatch( + Pattern.compile("All databases created after (.+) and that are ready:")); + assertThat(out).contains("All backups, listed using pagination:"); + // All the above tests should include the created backup exactly once, i.e. exactly 7 times. + assertThat(countOccurrences(out, backupId.getName())).isEqualTo(7); + + // Try the restore operation in a retry loop, as there is a limit on the number of restore + // operations that is allowed to execute simultaneously, and we should retry if we hit this + // limit. + boolean restored = false; + int restoreAttempts = 0; + while (true) { + try { + out = runSample("restorebackup"); + assertThat(out).contains( + "Restored database [" + + dbId.getName() + + "] from [" + + backupId.getName() + + "]"); + restored = true; + break; + } catch (SpannerException e) { + if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION + && e.getMessage() + .contains("Please retry the operation once the pending restores complete")) { + restoreAttempts++; + if (restoreAttempts == 10) { + System.out.println( + "Restore operation failed 10 times because of other pending restores. " + + "Giving up restore."); + break; + } + Uninterruptibles.sleepUninterruptibly(60L, TimeUnit.SECONDS); + } else { + throw e; + } + } + } + + if (restored) { + out = runSample("listdatabaseoperations"); + assertThat(out).contains( + String.format( + "Database %s restored from backup", + DatabaseId.of( + dbId.getInstanceId(), + SpannerSample.createRestoredSampleDbId(dbId)) + .getName())); + } + + out = runSample("updatebackup"); + assertThat(out).contains( + String.format("Updated backup [" + backupId + "]")); + + // Drop the restored database before we try to delete the backup. + // Otherwise the delete backup operation might fail as the backup is still in use by + // the OptimizeRestoredDatabase operation. + dbClient.dropDatabase( + dbId.getInstanceId().getInstance(), SpannerSample.createRestoredSampleDbId(dbId)); + + out = runSample("deletebackup"); + assertThat(out).contains("Deleted backup [" + backupId + "]"); + } + + @Test + public void testEncryptedDatabaseAndBackupSamples() throws Exception { + String projectId = spanner.getOptions().getProjectId(); + // Create a separate instance for this test to prevent multiple parallel backup operations on + // the same instance that need to wait for each other. + String instanceId = String.format("encrypted-test-%s", UUID.randomUUID()); + InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); + instanceAdminClient + .createInstance(InstanceInfo.newBuilder(InstanceId.of(projectId, instanceId)) + .setDisplayName("Encrypted test instance") + .setInstanceConfigId(InstanceConfigId.of(projectId, "regional-" + keyLocation)) + .setNodeCount(1).build()) + .get(); + try { + String out = SampleRunner + .runSample(() -> CreateDatabaseWithEncryptionKey.createDatabaseWithEncryptionKey(dbClient, + projectId, instanceId, encryptedDatabaseId, key)); + assertThat(out).contains(String.format( + "Database projects/%s/instances/%s/databases/%s created with encryption key %s", + projectId, instanceId, encryptedDatabaseId, key)); + + out = SampleRunner.runSampleWithRetry( + () -> CreateBackupWithEncryptionKey.createBackupWithEncryptionKey(dbClient, projectId, + instanceId, encryptedDatabaseId, encryptedBackupId, key), + new ShouldRetryBackupOperation()); + assertThat(out).containsMatch(String.format( + "Backup projects/%s/instances/%s/backups/%s of size \\d+ bytes " + + "was created at (.*) using encryption key %s", + projectId, instanceId, encryptedBackupId, key)); + + out = SampleRunner.runSampleWithRetry( + () -> RestoreBackupWithEncryptionKey.restoreBackupWithEncryptionKey(dbClient, projectId, + instanceId, encryptedBackupId, encryptedRestoreId, key), + new ShouldRetryBackupOperation()); + assertThat(out).contains(String.format( + "Database projects/%s/instances/%s/databases/%s" + + " restored to projects/%s/instances/%s/databases/%s" + + " from backup projects/%s/instances/%s/backups/%s" + " using encryption key %s", + projectId, instanceId, encryptedDatabaseId, projectId, instanceId, encryptedRestoreId, + projectId, instanceId, encryptedBackupId, key)); + } finally { + // Delete the backups from the test instance first, as the instance can only be deleted once + // all backups have been deleted. + deleteAllBackups(instanceId); + instanceAdminClient.deleteInstance(instanceId); + } + } + + private static void deleteAllBackups(String instanceId) throws InterruptedException { + for (Backup backup : dbClient.listBackups(instanceId).iterateAll()) { + int attempts = 0; + while (attempts < 30) { + try { + attempts++; + backup.delete(); + break; + } catch (SpannerException e) { + if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION && e.getMessage() + .contains("Please try deleting the backup once the restore or post-restore optimize " + + "operations have completed on these databases.")) { + // Wait 30 seconds and then retry. + Thread.sleep(30_000L); + } else { + throw e; + } + } + } + } + } + + private String runSampleRunnable(Runnable sample) { + PrintStream stdOut = System.out; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(bout); + System.setOut(out); + sample.run(); + System.setOut(stdOut); + return bout.toString(); + } + + @Test + public void testCreateInstanceSample() { + String instanceId = formatForTest("sample-inst"); + String out = + runSampleRunnable(() -> { + try { + CreateInstanceExample.createInstance( + dbId.getInstanceId().getProject(), instanceId); + } finally { + spanner.getInstanceAdminClient().deleteInstance(instanceId); + } + }); + assertThat(out) + .contains( + String.format( + "Instance %s was successfully created", + InstanceId.of(dbId.getInstanceId().getProject(), instanceId))); + } + + private static int countOccurrences(String input, String search) { + return input.split(search).length - 1; + } + + private static String toComparableId(String baseId, String existingId) { + String zeroUuid = "00000000-0000-0000-0000-0000-00000000"; + int shouldBeLength = (baseId + "-" + zeroUuid).length(); + int missingLength = shouldBeLength - existingId.length(); + return existingId + zeroUuid.substring(zeroUuid.length() - missingLength); + } + + private static Pattern getTestDbIdPattern(String baseDbId) { + return Pattern.compile( + baseDbId + "-[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{8}", + Pattern.CASE_INSENSITIVE); + } + + static String formatForTest(String name) { + return name + "-" + UUID.randomUUID().toString().substring(0, DBID_LENGTH); + } + + static class ShouldRetryBackupOperation implements Predicate { + private static final int MAX_ATTEMPTS = 20; + private int attempts = 0; + + @Override + public boolean test(SpannerException e) { + if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION + && e.getMessage().contains("Please retry the operation once the pending")) { + attempts++; + if (attempts == MAX_ATTEMPTS) { + // Throw custom exception so it is easier to locate in the log why it went wrong. + throw SpannerExceptionFactory.newSpannerException(ErrorCode.DEADLINE_EXCEEDED, + String.format("Operation failed %d times because of other pending operations. " + + "Giving up operation.\n", attempts), + e); + } + // Wait one minute before retrying. + Uninterruptibles.sleepUninterruptibly(60L, TimeUnit.SECONDS); + return true; + } + return false; + } + } +} diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/UpdateDatabaseSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/UpdateDatabaseSampleIT.java similarity index 53% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/UpdateDatabaseSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/UpdateDatabaseSampleIT.java index acac98cde4..29a99ed3b8 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/UpdateDatabaseSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/UpdateDatabaseSampleIT.java @@ -14,58 +14,49 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; +import com.example.spanner.SampleTestBase; +import com.example.spanner.admin.archived.UpdateDatabaseSample; import com.google.api.gax.longrunning.OperationFuture; -import com.google.common.collect.Lists; -import com.google.protobuf.FieldMask; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.DatabaseInfo.DatabaseField; import com.google.spanner.admin.database.v1.UpdateDatabaseMetadata; -import com.google.spanner.admin.database.v1.UpdateDatabaseRequest; +import java.util.Collections; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class UpdateDatabaseSampleIT extends SampleTestBaseV2 { +public class UpdateDatabaseSampleIT extends SampleTestBase { @Test public void testUpdateDatabase() throws Exception { // Create database final String databaseId = idGenerator.generateDatabaseId(); databaseAdminClient - .createDatabaseAsync(getInstanceName(projectId, instanceId), - "CREATE DATABASE `" + databaseId + "`") + .createDatabase(instanceId, databaseId, Collections.emptyList()) .get(5, TimeUnit.MINUTES); // Runs sample final String out = SampleRunner.runSample( () -> UpdateDatabaseSample.updateDatabase(projectId, instanceId, databaseId)); + + DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); assertTrue( "Expected that database would have been updated. Output received was " + out, - out.contains(String.format( - "Updated database %s", DatabaseName.of(projectId, instanceId, databaseId)))); + out.contains(String.format("Updated database %s", dbId))); // Cleanup - final com.google.spanner.admin.database.v1.Database database = - com.google.spanner.admin.database.v1.Database.newBuilder() - .setName(DatabaseName.of(projectId, instanceId, databaseId).toString()) - .setEnableDropProtection(false).build(); - final UpdateDatabaseRequest updateDatabaseRequest = - UpdateDatabaseRequest.newBuilder() - .setDatabase(database) - .setUpdateMask( - FieldMask.newBuilder().addAllPaths( - Lists.newArrayList("enable_drop_protection")).build()) - .build(); - + Database databaseToUpdate = + databaseAdminClient.newDatabaseBuilder(dbId).disableDropProtection().build(); OperationFuture operation = - databaseAdminClient.updateDatabaseAsync(updateDatabaseRequest); + databaseAdminClient.updateDatabase(databaseToUpdate, DatabaseField.DROP_PROTECTION); Database updatedDb = operation.get(5, TimeUnit.MINUTES); - assertFalse(updatedDb.getEnableDropProtection()); + assertFalse(updatedDb.isDropProtectionEnabled()); } } diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/UpdateDatabaseWithDefaultLeaderSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/archived/UpdateDatabaseWithDefaultLeaderSampleIT.java similarity index 61% rename from samples/snippets/src/test/java/com/example/spanner/admin/generated/UpdateDatabaseWithDefaultLeaderSampleIT.java rename to samples/snippets/src/test/java/com/example/spanner/admin/archived/UpdateDatabaseWithDefaultLeaderSampleIT.java index 3ec3587288..ce657575f0 100644 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/UpdateDatabaseWithDefaultLeaderSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/admin/archived/UpdateDatabaseWithDefaultLeaderSampleIT.java @@ -14,40 +14,45 @@ * limitations under the License. */ -package com.example.spanner.admin.generated; +package com.example.spanner.admin.archived; import static org.junit.Assert.assertTrue; import com.example.spanner.SampleRunner; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.instance.v1.InstanceConfig; +import com.example.spanner.SampleTestBase; +import com.example.spanner.admin.archived.UpdateDatabaseWithDefaultLeaderSample; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.InstanceConfig; +import com.google.cloud.spanner.InstanceConfigId; +import java.util.Collections; import java.util.concurrent.TimeUnit; import org.junit.Test; -public class UpdateDatabaseWithDefaultLeaderSampleIT extends SampleTestBaseV2 { +public class UpdateDatabaseWithDefaultLeaderSampleIT extends SampleTestBase { @Test public void testUpdateDatabaseWithDefaultLeader() throws Exception { // Create database final String databaseId = idGenerator.generateDatabaseId(); final Database createdDatabase = databaseAdminClient - .createDatabaseAsync(getInstanceName(projectId, multiRegionalInstanceId), - "CREATE DATABASE `" + databaseId + "`") + .createDatabase(multiRegionalInstanceId, databaseId, Collections.emptyList()) .get(5, TimeUnit.MINUTES); final String defaultLeader = createdDatabase.getDefaultLeader(); // Finds a possible new leader option - final String instanceConfigId = - instanceAdminClient.getInstance(getInstanceName(projectId, multiRegionalInstanceId)) - .getConfig(); - final InstanceConfig config = instanceAdminClient.getInstanceConfig(instanceConfigId); - final String newLeader = - config.getLeaderOptionsList().stream() - .filter(leader -> !leader.equals(defaultLeader)) - .findFirst().orElseThrow(() -> - new RuntimeException("Expected to find a leader option different than " - + defaultLeader) - ); + final InstanceConfigId instanceConfigId = instanceAdminClient + .getInstance(multiRegionalInstanceId) + .getInstanceConfigId(); + final InstanceConfig config = instanceAdminClient + .getInstanceConfig(instanceConfigId.getInstanceConfig()); + final String newLeader = config + .getLeaderOptions() + .stream() + .filter(leader -> !leader.equals(defaultLeader)) + .findFirst() + .orElseThrow(() -> + new RuntimeException("Expected to find a leader option different than " + defaultLeader) + ); // Runs sample final String out = SampleRunner.runSample(() -> UpdateDatabaseWithDefaultLeaderSample diff --git a/samples/snippets/src/test/java/com/example/spanner/admin/generated/SpannerSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/admin/generated/SpannerSampleIT.java deleted file mode 100644 index cf719ff9e4..0000000000 --- a/samples/snippets/src/test/java/com/example/spanner/admin/generated/SpannerSampleIT.java +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Copyright 2017 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; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertTrue; - -import com.example.spanner.SampleRunner; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Instance; -import com.google.cloud.spanner.InstanceAdminClient; -import com.google.cloud.spanner.InstanceConfigId; -import com.google.cloud.spanner.InstanceId; -import com.google.cloud.spanner.InstanceInfo; -import com.google.cloud.spanner.Options; -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.cloud.spanner.admin.database.v1.DatabaseAdminClient; -import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.Uninterruptibles; -import com.google.spanner.admin.database.v1.Backup; -import com.google.spanner.admin.database.v1.BackupName; -import com.google.spanner.admin.database.v1.Database; -import com.google.spanner.admin.database.v1.DatabaseName; -import com.google.spanner.admin.database.v1.InstanceName; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.function.Predicate; -import java.util.regex.Pattern; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit tests for {@code SpannerSample} - */ -@RunWith(JUnit4.class) -@SuppressWarnings("checkstyle:abbreviationaswordinname") -public class SpannerSampleIT extends SampleTestBaseV2 { - - private static final int DBID_LENGTH = 20; - // The instance needs to exist for tests to pass. - private static final String instanceId = System.getProperty("spanner.test.instance"); - private static final String baseDbId = System.getProperty("spanner.sample.database"); - private static final String keyLocation = - Preconditions.checkNotNull(System.getProperty("spanner.test.key.location")); - private static final String keyRing = - Preconditions.checkNotNull(System.getProperty("spanner.test.key.ring")); - private static final String keyName = - Preconditions.checkNotNull(System.getProperty("spanner.test.key.name")); - private static final String encryptedBackupId = formatForTest(baseDbId); - private static final long STALE_INSTANCE_THRESHOLD_SECS = - TimeUnit.SECONDS.convert(24L, TimeUnit.HOURS); - static Spanner spanner; - static DatabaseAdminClient databaseAdminClient; - private static String key; - private long lastUpdateDataTimeInMillis; - - private String runSample(String command, String databaseId) throws Exception { - PrintStream stdOut = System.out; - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bout); - System.setOut(out); - SpannerSample.main(new String[]{command, instanceId, databaseId, null}); - System.setOut(stdOut); - return bout.toString(); - } - - private String runSample(String command, String databaseId, String backupId) throws Exception { - PrintStream stdOut = System.out; - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bout); - System.setOut(out); - SpannerSample.main(new String[]{command, instanceId, databaseId, backupId}); - System.setOut(stdOut); - return bout.toString(); - } - - @BeforeClass - public static void setUp() throws Exception { - SpannerOptions options = - SpannerOptions.newBuilder().setAutoThrottleAdministrativeRequests().build(); - spanner = options.getService(); - databaseAdminClient = DatabaseAdminClient.create(); - // Delete stale test databases that have been created earlier by this test, but not deleted. - deleteStaleTestDatabases(); - key = - String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - options.getProjectId(), keyLocation, keyRing, keyName); - - /* - * Delete stale instances that have been created earlier by this test but not deleted. - * Backups needed to be deleted from the instance first, as the instance can only be - * deleted once all backups have been deleted. - * */ - deleteStaleEncryptedTestInstances(); - } - - /** - * Deleting all the test instances with name starting with 'encrypted-test-' and were created - * before 24 hours. - * - * @throws InterruptedException If Thread.sleep() interrupted - */ - private static void deleteStaleEncryptedTestInstances() throws InterruptedException { - Timestamp now = Timestamp.now(); - - for (Instance instance : - spanner - .getInstanceAdminClient() - .listInstances(Options.filter("name:encrypted-test-")) - .iterateAll()) { - if ((now.getSeconds() - instance.getCreateTime().getSeconds()) - > STALE_INSTANCE_THRESHOLD_SECS) { - deleteAllBackups(instance.getId().getInstance()); - instance.delete(); - } - } - } - - static void deleteStaleTestDatabases() throws IOException { - Timestamp now = Timestamp.now(); - Pattern samplePattern = getTestDbIdPattern(SpannerSampleIT.baseDbId); - Pattern restoredPattern = getTestDbIdPattern("restored"); - try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) { - for (Database db : databaseAdminClient.listDatabases(InstanceName.of(projectId, instanceId)) - .iterateAll()) { - DatabaseName databaseName = DatabaseName.parse(db.getName()); - if (TimeUnit.HOURS.convert(now.getSeconds() - db.getCreateTime().getSeconds(), - TimeUnit.SECONDS) > 24) { - if (databaseName.getDatabase().length() >= DBID_LENGTH) { - if (samplePattern.matcher( - toComparableId(SpannerSampleIT.baseDbId, databaseName.getDatabase())).matches()) { - databaseAdminClient.dropDatabase(db.getName()); - } - if (restoredPattern.matcher(toComparableId("restored", databaseName.getDatabase())) - .matches()) { - databaseAdminClient.dropDatabase(db.getName()); - } - } - } - } - } - } - - @AfterClass - public static void tearDown() { - databaseAdminClient.deleteBackup(BackupName.of(projectId, instanceId, encryptedBackupId)); - spanner.close(); - } - - @Test - public void testSample() throws Exception { - String databaseId = idGenerator.generateDatabaseId(); - DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); - assertThat(instanceId).isNotNull(); - assertThat(databaseId).isNotNull(); - String out = runSample("createdatabase", databaseId); - assertThat(out).contains("Created database"); - assertThat(out).contains(dbId.getName()); - - System.out.println("Write data to sample tables ..."); - runSample("write", databaseId); - - System.out.println("Delete data to sample tables ..."); - out = runSample("delete", databaseId); - assertThat(out).contains("Records deleted."); - - runSample("write", databaseId); - - System.out.println("Read data from sample tables ..."); - out = runSample("read", databaseId); - assertThat(out).contains("1 1 Total Junk"); - - out = runSample("query", databaseId); - assertThat(out).contains("1 1 Total Junk"); - runSample("addmarketingbudget", databaseId); - - // wait for 15 seconds to elapse and then run an update, and query for stale data - lastUpdateDataTimeInMillis = System.currentTimeMillis(); - while (System.currentTimeMillis() < lastUpdateDataTimeInMillis + 16000) { - Thread.sleep(1000); - } - runSample("update", databaseId); - - System.out.println("Read stale data from sample tables ..."); - out = runSample("readstaledata", databaseId); - assertThat(out).contains("1 1 NULL"); - runSample("writetransaction", databaseId); - - System.out.println("Query marketing budget ..."); - out = runSample("querymarketingbudget", databaseId); - assertThat(out).contains("1 1 300000"); - assertThat(out).contains("2 2 300000"); - - System.out.println("Add index ..."); - runSample("addindex", databaseId); - - System.out.println("Query index ..."); - out = runSample("queryindex", databaseId); - assertThat(out).contains("Go, Go, Go"); - assertThat(out).contains("Forever Hold Your Peace"); - assertThat(out).doesNotContain("Green"); - - System.out.println("Read index ..."); - out = runSample("readindex", databaseId); - assertThat(out).contains("Go, Go, Go"); - assertThat(out).contains("Forever Hold Your Peace"); - assertThat(out).contains("Green"); - - System.out.println("Add Storing index ..."); - runSample("addstoringindex", databaseId); - out = runSample("readstoringindex", databaseId); - assertThat(out).contains("300000"); - - System.out.println("Read storing index ..."); - out = runSample("readonlytransaction", databaseId); - assertThat(out.replaceAll("[\r\n]+", " ")).containsMatch("(Total Junk.*){2}"); - - out = runSample("addcommittimestamp", databaseId); - assertThat(out).contains("Added LastUpdateTime as a commit timestamp column"); - - runSample("updatewithtimestamp", databaseId); - out = runSample("querywithtimestamp", databaseId); - assertThat(out).contains("1 1 1000000"); - assertThat(out).contains("2 2 750000"); - - out = runSample("createtablewithtimestamp", databaseId); - assertThat(out).contains("Created Performances table in database"); - - runSample("writewithtimestamp", databaseId); - out = runSample("queryperformancestable", databaseId); - assertThat(out).contains("1 4 2017-10-05 11000"); - assertThat(out).contains("1 19 2017-11-02 15000"); - assertThat(out).contains("2 42 2017-12-23 7000"); - - runSample("writestructdata", databaseId); - out = runSample("querywithstruct", databaseId); - assertThat(out).startsWith("6\n"); - - out = runSample("querywitharrayofstruct", databaseId); - assertThat(out).startsWith("8\n7\n6"); - - out = runSample("querystructfield", databaseId); - assertThat(out).startsWith("6\n"); - - out = runSample("querynestedstructfield", databaseId); - assertThat(out).contains("6 Imagination\n"); - assertThat(out).contains("9 Imagination\n"); - - runSample("insertusingdml", databaseId); - out = runSample("querysingerstable", databaseId); - assertThat(out).contains("Virginia Watson"); - - runSample("updateusingdml", databaseId); - out = runSample("querymarketingbudget", databaseId); - assertThat(out).contains("1 1 2000000"); - - runSample("deleteusingdml", databaseId); - out = runSample("querysingerstable", databaseId); - assertThat(out).doesNotContain("Alice Trentor"); - - out = runSample("updateusingdmlwithtimestamp", databaseId); - assertThat(out).contains("2 records updated"); - - out = runSample("writeandreadusingdml", databaseId); - assertThat(out).contains("Timothy Campbell"); - - runSample("updateusingdmlwithstruct", databaseId); - out = runSample("querysingerstable", databaseId); - assertThat(out).contains("Timothy Grant"); - - runSample("writeusingdml", databaseId); - out = runSample("querysingerstable", databaseId); - assertThat(out).contains("Melissa Garcia"); - assertThat(out).contains("Russell Morales"); - assertThat(out).contains("Jacqueline Long"); - assertThat(out).contains("Dylan Shaw"); - out = runSample("querywithparameter", databaseId); - assertThat(out).contains("12 Melissa Garcia"); - - runSample("writewithtransactionusingdml", databaseId); - out = runSample("querymarketingbudget", databaseId); - assertThat(out).contains("1 1 2200000"); - assertThat(out).contains("2 2 550000"); - - runSample("updateusingpartitioneddml", databaseId); - out = runSample("querymarketingbudget", databaseId); - assertThat(out).contains("1 1 2200000"); - assertThat(out).contains("2 2 100000"); - - runSample("deleteusingpartitioneddml", databaseId); - out = runSample("querysingerstable", databaseId); - assertThat(out).doesNotContain("Timothy Grant"); - assertThat(out).doesNotContain("Melissa Garcia"); - assertThat(out).doesNotContain("Russell Morales"); - assertThat(out).doesNotContain("Jacqueline Long"); - assertThat(out).doesNotContain("Dylan Shaw"); - - out = runSample("updateusingbatchdml", databaseId); - assertThat(out).contains("1 record updated by stmt 0"); - assertThat(out).contains("1 record updated by stmt 1"); - - out = runSample("createtablewithdatatypes", databaseId); - assertThat(out).contains("Created Venues table in database"); - - runSample("writedatatypesdata", databaseId); - out = runSample("querywitharray", databaseId); - assertThat(out).contains("19 Venue 19 2020-11-01"); - assertThat(out).contains("42 Venue 42 2020-10-01"); - - out = runSample("querywithbool", databaseId); - assertThat(out).contains("19 Venue 19 true"); - - out = runSample("querywithbytes", databaseId); - assertThat(out).contains("4 Venue 4"); - - out = runSample("querywithdate", databaseId); - assertThat(out).contains("4 Venue 4 2018-09-02"); - assertThat(out).contains("42 Venue 42 2018-10-01"); - - out = runSample("querywithfloat", databaseId); - assertThat(out).contains("4 Venue 4 0.8"); - assertThat(out).contains("19 Venue 19 0.9"); - - out = runSample("querywithint", databaseId); - assertThat(out).contains("19 Venue 19 6300"); - assertThat(out).contains("42 Venue 42 3000"); - - out = runSample("querywithstring", databaseId); - assertThat(out).contains("42 Venue 42"); - - out = runSample("querywithtimestampparameter", databaseId); - assertThat(out).contains("4 Venue 4"); - assertThat(out).contains("19 Venue 19"); - assertThat(out).contains("42 Venue 42"); - - out = runSample("querywithnumeric", databaseId); - assertThat(out).contains("19 Venue 19 1200100"); - assertThat(out).contains("42 Venue 42 390650.99"); - - out = runSample("clientwithqueryoptions", databaseId); - assertThat(out).contains("1 1 Total Junk"); - out = runSample("querywithqueryoptions", databaseId); - assertThat(out).contains("1 1 Total Junk"); - } - - @Test - public void testBackupSamples_withoutEncryption() { - String databaseId = idGenerator.generateDatabaseId(); - DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); - String restoreDatabaseId = idGenerator.generateDatabaseId(); - String backupId = idGenerator.generateBackupId(); - - try { - assertThat(instanceId).isNotNull(); - assertThat(databaseId).isNotNull(); - - System.out.println("Creating Database ..."); - String out = runSample("createdatabase", databaseId); - assertThat(out).contains("Created database"); - assertThat(out).contains(dbId.getName()); - - BackupName backupName = BackupName.of(projectId, instanceId, backupId); - - System.out.println("Creating Backup ..."); - out = runSample("createbackup", databaseId, backupId); - assertThat(out).contains("Created backup [" + backupName.toString() + "]"); - - // TODO: remove try-catch when filtering on metadata fields works. - try { - System.out.println("List Backup Operations ..."); - out = runSample("listbackupoperations", databaseId, backupId); - assertThat(out).contains( - String.format( - "Backup %s on database %s pending:", backupName, dbId.getName())); - assertTrue("Out does not contain copy backup operations", out.contains( - "Copy Backup Operations")); - } catch (SpannerException e) { - assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT); - assertThat(e.getMessage()).contains("Cannot evaluate filter expression"); - } - - System.out.println("List Backup ..."); - out = runSample("listbackups", databaseId, backupId); - assertThat(out).contains("All backups:"); - assertThat(out).contains( - String.format("All backups with backup name containing \"%s\":", backupId)); - assertThat(out).contains(String.format( - "All backups for databases with a name containing \"%s\":", - dbId.getDatabase())); - assertThat(out).contains( - String.format("All backups that expire before")); - assertThat(out).contains("All backups with size greater than 100 bytes:"); - assertThat(out).containsMatch( - Pattern.compile("All databases created after (.+) and that are ready:")); - assertThat(out).contains("All backups, listed using pagination:"); - // All the above tests should include the created backup exactly once, i.e. exactly 6 times. - assertThat(countOccurrences(out, backupName.toString())).isEqualTo(6); - - // Try the restore operation in a retry loop, as there is a limit on the number of restore - // operations that is allowed to execute simultaneously, and we should retry if we hit this - // limit. - boolean restored = false; - int restoreAttempts = 0; - while (true) { - try { - System.out.println("Restore Backup ..."); - out = runSample("restorebackup", restoreDatabaseId, backupId); - assertThat(out).contains( - "Restored database [" - + DatabaseName.of(projectId, instanceId, restoreDatabaseId).toString() - + "] from [" - + backupName - + "]"); - restored = true; - break; - } catch (SpannerException e) { - if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION - && e.getMessage() - .contains("Please retry the operation once the pending restores complete")) { - restoreAttempts++; - if (restoreAttempts == 10) { - System.out.println( - "Restore operation failed 10 times because of other pending restores. " - + "Giving up restore."); - break; - } - Uninterruptibles.sleepUninterruptibly(60L, TimeUnit.SECONDS); - } else { - throw e; - } - } - } - - if (restored) { - System.out.println("List Database Operations ..."); - out = runSample("listdatabaseoperations", restoreDatabaseId); - assertThat(out).contains( - String.format( - "Database %s restored from backup", - DatabaseId.of(dbId.getInstanceId(), restoreDatabaseId).getName())); - } - - System.out.println("Updating backup ..."); - out = runSample("updatebackup", databaseId, backupId); - assertThat(out).contains( - String.format("Updated backup [" + backupId + "]")); - - // Drop the restored database before we try to delete the backup. - // Otherwise the delete backup operation might fail as the backup is still in use by - // the OptimizeRestoredDatabase operation. - databaseAdminClient.dropDatabase(DatabaseName.of(projectId, - dbId.getInstanceId().getInstance(), restoreDatabaseId)); - - System.out.println("Deleting Backup ..."); - out = runSample("deletebackup", databaseId, backupId); - assertThat(out).contains("Deleted backup [" + backupId + "]"); - - } catch (Exception ex) { - Assert.fail("Exception raised => " + ex.getCause()); - } - } - - @Test - public void testCancelBackupSamples() { - String databaseId = idGenerator.generateDatabaseId(); - DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); - - try { - assertThat(instanceId).isNotNull(); - assertThat(databaseId).isNotNull(); - - String out = runSample("createdatabase", databaseId); - assertThat(out).contains("Created database"); - assertThat(out).contains(dbId.getName()); - - String backupId = idGenerator.generateBackupId(); - - out = runSample("cancelcreatebackup", databaseId, backupId); - assertThat(out).contains( - "Backup operation for [" + backupId + "_cancel] successfully"); - } catch (Exception ex) { - Assert.fail("Exception raised => " + ex.getCause()); - } - } - - @Test - public void testEncryptedDatabaseAndBackupSamples() throws Exception { - String projectId = spanner.getOptions().getProjectId(); - String databaseId = idGenerator.generateDatabaseId(); - String restoreId = idGenerator.generateDatabaseId(); - // Create a separate instance for this test to prevent multiple parallel backup operations on - // the same instance that need to wait for each other. - String instanceId = idGenerator.generateInstanceId(); - InstanceAdminClient instanceAdminClient = spanner.getInstanceAdminClient(); - instanceAdminClient - .createInstance(InstanceInfo.newBuilder(InstanceId.of(projectId, instanceId)) - .setDisplayName("Encrypted test instance") - .setInstanceConfigId(InstanceConfigId.of(projectId, "regional-" + keyLocation)) - .setNodeCount(1).build()) - .get(); - try { - String out = SampleRunner - .runSample(() -> SpannerSample.createDatabase( - databaseAdminClient, InstanceName.of(projectId, instanceId), databaseId)); - assertThat(out).contains(String.format( - "Created database [%s]", DatabaseName.of(projectId, instanceId, databaseId))); - - out = SampleRunner.runSampleWithRetry( - () -> CreateBackupWithEncryptionKey.createBackupWithEncryptionKey(databaseAdminClient, - projectId, - instanceId, databaseId, encryptedBackupId, key), - new ShouldRetryBackupOperation()); - assertThat(out).containsMatch(String.format( - "Backup projects/%s/instances/%s/backups/%s of size \\d+ bytes " - + "was created at (.*) using encryption key %s", - projectId, instanceId, encryptedBackupId, key)); - - out = SampleRunner.runSampleWithRetry( - () -> RestoreBackupWithEncryptionKey.restoreBackupWithEncryptionKey(databaseAdminClient, - projectId, instanceId, encryptedBackupId, restoreId, key), - new ShouldRetryBackupOperation()); - assertThat(out).contains(String.format( - "Database projects/%s/instances/%s/databases/%s" - + " restored to projects/%s/instances/%s/databases/%s" - + " from backup projects/%s/instances/%s/backups/%s" + " using encryption key %s", - projectId, instanceId, databaseId, projectId, instanceId, restoreId, - projectId, instanceId, encryptedBackupId, key)); - } finally { - // Delete the backups from the test instance first, as the instance can only be deleted once - // all backups have been deleted. - deleteAllBackups(instanceId); - instanceAdminClient.deleteInstance(instanceId); - } - } - - @Test - public void testDeleteBackups() { - try { - String projectId = spanner.getOptions().getProjectId(); - String databaseId = idGenerator.generateDatabaseId(); - String backupId = idGenerator.generateBackupId(); - - String out = SampleRunner - .runSample(() -> SpannerSample.createDatabase( - databaseAdminClient, InstanceName.of(projectId, instanceId), databaseId)); - assertThat(out).contains(String.format( - "Created database [%s]", DatabaseName.of(projectId, instanceId, databaseId))); - - out = SampleRunner.runSampleWithRetry( - () -> CreateBackupWithEncryptionKey.createBackupWithEncryptionKey(databaseAdminClient, - projectId, instanceId, databaseId, backupId, key), - new ShouldRetryBackupOperation()); - assertThat(out).containsMatch(String.format( - "Backup projects/%s/instances/%s/backups/%s of size \\d+ bytes " - + "was created at (.*) using encryption key %s", - projectId, instanceId, backupId, key)); - - out = runSample("deletebackup", databaseId, backupId); - assertThat(out).contains("Deleted backup [" + backupId + "]"); - } catch (Exception ex) { - Assert.fail("Exception raised => " + ex.getCause()); - } - } - - private static void deleteAllBackups(String instanceId) throws InterruptedException { - InstanceName instanceName = InstanceName.of(projectId, instanceId); - for (Backup backup : databaseAdminClient.listBackups(instanceName.toString()).iterateAll()) { - int attempts = 0; - while (attempts < 30) { - try { - attempts++; - databaseAdminClient.deleteBackup(backup.getName()); - break; - } catch (SpannerException e) { - if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION && e.getMessage() - .contains("Please try deleting the backup once the restore or post-restore optimize " - + "operations have completed on these databases.")) { - // Wait 30 seconds and then retry. - Thread.sleep(30_000L); - } else { - throw e; - } - } - } - } - } - - private String runSampleRunnable(Runnable sample) { - PrintStream stdOut = System.out; - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bout); - System.setOut(out); - sample.run(); - System.setOut(stdOut); - return bout.toString(); - } - - @Test - public void testCreateInstanceSample() { - String databaseId = idGenerator.generateDatabaseId(); - DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId); - - String instanceId = formatForTest("sample-inst"); - String out = - runSampleRunnable(() -> { - try { - CreateInstanceExample.createInstance( - dbId.getInstanceId().getProject(), instanceId); - } catch (IOException ex) { - System.out.println("Got exception => " + ex); - } finally { - spanner.getInstanceAdminClient().deleteInstance(instanceId); - } - }); - assertThat(out) - .contains( - String.format( - "Instance %s was successfully created", - InstanceId.of(dbId.getInstanceId().getProject(), instanceId))); - } - - private static int countOccurrences(String input, String search) { - return input.split(search).length - 1; - } - - private static String toComparableId(String baseId, String existingId) { - String zeroUuid = "00000000-0000-0000-0000-0000-00000000"; - int shouldBeLength = (baseId + "-" + zeroUuid).length(); - int missingLength = shouldBeLength - existingId.length(); - return existingId + zeroUuid.substring(zeroUuid.length() - missingLength); - } - - private static Pattern getTestDbIdPattern(String baseDbId) { - return Pattern.compile( - baseDbId + "-[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{8}", - Pattern.CASE_INSENSITIVE); - } - - static String formatForTest(String name) { - return name + "-" + UUID.randomUUID().toString().substring(0, DBID_LENGTH); - } - - static class ShouldRetryBackupOperation implements Predicate { - - private static final int MAX_ATTEMPTS = 20; - private int attempts = 0; - - @Override - public boolean test(SpannerException e) { - if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION - && e.getMessage().contains("Please retry the operation once the pending")) { - attempts++; - if (attempts == MAX_ATTEMPTS) { - // Throw custom exception so it is easier to locate in the log why it went wrong. - throw SpannerExceptionFactory.newSpannerException(ErrorCode.DEADLINE_EXCEEDED, - String.format("Operation failed %d times because of other pending operations. " - + "Giving up operation.\n", attempts), - e); - } - // Wait one minute before retrying. - Uninterruptibles.sleepUninterruptibly(60L, TimeUnit.SECONDS); - return true; - } - return false; - } - } -}