diff --git a/README.md b/README.md index baac29f6974..86dbd0f39c0 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ If you are using Maven without BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies: ```Groovy -implementation platform('com.google.cloud:libraries-bom:26.2.0') +implementation platform('com.google.cloud:libraries-bom:26.3.0') implementation 'com.google.cloud:google-cloud-spanner' ``` @@ -261,6 +261,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/ | Create Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/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/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/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/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/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/CreateDatabaseWithEncryptionKey.java) | +| Create Database With Proto Descriptor | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithProtoDescriptor.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/CreateDatabaseWithProtoDescriptor.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/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/CreateDatabaseWithVersionRetentionPeriodSample.java) | | Create Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/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/CreateInstanceConfigSample.java) | | Create Instance Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/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/CreateInstanceExample.java) | @@ -290,12 +291,14 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/ | Pg Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/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/PgSpannerSample.java) | | Pg Update Using Dml Returning Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgUpdateUsingDmlReturningSample.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/PgUpdateUsingDmlReturningSample.java) | | Query Information Schema Database Options Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryInformationSchemaDatabaseOptionsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryInformationSchemaDatabaseOptionsSample.java) | +| Query Proto Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryProtoColumnSample.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/QueryProtoColumnSample.java) | | Query With Json Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithJsonParameterSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryWithJsonParameterSample.java) | | Query With Jsonb Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithJsonbParameterSample.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/QueryWithJsonbParameterSample.java) | | Query With Numeric Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithNumericParameterSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryWithNumericParameterSample.java) | | Quickstart Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QuickstartSample.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/QuickstartSample.java) | | Read Data With Database Role | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ReadDataWithDatabaseRole.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/ReadDataWithDatabaseRole.java) | | Restore Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/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/RestoreBackupWithEncryptionKey.java) | +| Singer Proto | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/SingerProto.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/SingerProto.java) | | Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/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/SpannerSample.java) | | Statement Timeout Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/StatementTimeoutExample.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/StatementTimeoutExample.java) | | Tag Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/TagSample.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/TagSample.java) | @@ -305,6 +308,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/ | Update Json Data Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UpdateJsonDataSample.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/UpdateJsonDataSample.java) | | 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 Proto Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/UpdateProtoColumnSample.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/UpdateProtoColumnSample.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) | diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml index 8e4710354e3..9950d9f62b3 100644 --- a/google-cloud-spanner/clirr-ignored-differences.xml +++ b/google-cloud-spanner/clirr-ignored-differences.xml @@ -262,4 +262,55 @@ com/google/cloud/spanner/connection/Connection com.google.cloud.spanner.ResultSet analyzeUpdateStatement(com.google.cloud.spanner.Statement, com.google.cloud.spanner.ReadContext$QueryAnalyzeMode, com.google.cloud.spanner.Options$UpdateOption[]) + + 7012 + com/google/cloud/spanner/DatabaseAdminClient + com.google.spanner.admin.database.v1.GetDatabaseDdlResponse getDatabaseDdlResponse(java.lang.String, java.lang.String) + + + 7012 + com/google/cloud/spanner/DatabaseAdminClient + com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(com.google.cloud.spanner.Database, java.lang.Iterable, java.lang.String) + + + 7013 + com/google/cloud/spanner/DatabaseInfo$Builder + com.google.cloud.spanner.DatabaseInfo$Builder setProtoDescriptors(byte[]) + + + 7013 + com/google/cloud/spanner/DatabaseInfo$Builder + com.google.cloud.spanner.DatabaseInfo$Builder setProtoDescriptors(java.io.InputStream) + + + 7013 + com/google/cloud/spanner/DatabaseInfo$Builder + com.google.cloud.spanner.DatabaseInfo$Builder setProtoDescriptors(java.lang.String) + + + 7006 + com/google/cloud/spanner/spi/v1/GapicSpannerRpc + java.util.List getDatabaseDdl(java.lang.String) + java.util.List + com.google.spanner.admin.database.v1.GetDatabaseDdlResponse + + + 7005 + com/google/cloud/spanner/spi/v1/GapicSpannerRpc + com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(java.lang.String, java.lang.Iterable, java.lang.String) + com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(com.google.cloud.spanner.Database, java.lang.Iterable, java.lang.String) + + + 7006 + com/google/cloud/spanner/spi/v1/SpannerRpc + java.util.List getDatabaseDdl(java.lang.String) + java.util.List + com.google.spanner.admin.database.v1.GetDatabaseDdlResponse + + + 7005 + com/google/cloud/spanner/spi/v1/SpannerRpc + com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(java.lang.String, java.lang.Iterable, java.lang.String) + com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(com.google.cloud.spanner.Database, java.lang.Iterable, java.lang.String) + diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClient.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClient.java index 1363118e3aa..e4c27ff4ef0 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClient.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClient.java @@ -26,6 +26,7 @@ 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.GetDatabaseDdlResponse; import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.List; @@ -382,7 +383,8 @@ OperationFuture restoreDatabase(Restore resto * *

If an operation already exists with the given operation id, the operation will be resumed * and the returned future will complete when the original operation finishes. See more - * information in {@link com.google.cloud.spanner.spi.v1.GapicSpannerRpc#updateDatabaseDdl(String, + * information in {@link + * com.google.cloud.spanner.spi.v1.GapicSpannerRpc#updateDatabaseDdl(com.google.cloud.spanner.Database, * Iterable, String)} * *

Example to update the database DDL. @@ -407,6 +409,39 @@ OperationFuture updateDatabaseDdl( @Nullable String operationId) throws SpannerException; + /** + * Updates a database in a Cloud Spanner instance. Any proto descriptors that have been set for + * the {@link Database} instance will be included in the {@link UpdateDatabaseDdlRequest}. + * + *

If an operation already exists with the given operation id, the operation will be resumed + * and the returned future will complete when the original operation finishes. See more + * information in {@link + * com.google.cloud.spanner.spi.v1.GapicSpannerRpc#updateDatabaseDdl(com.google.cloud.spanner.Database, + * Iterable, String)} + * + *

Example to update the database DDL with proto descriptors. + * + *

{@code
+   * Database dbInfo =
+   *         dbClient
+   *            .newDatabaseBuilder(DatabaseId.of("my_project_id", "my_instance_id", "my_database_id"))
+   *            .setProtoDescriptors("com/google/cloud/spanner/descriptors.pb")
+   *            .build();
+   * dbAdminClient.updateDatabaseDdl(dbInfo,
+   *     Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"),
+   *     null).waitFor();
+   * }
+ * + * @param database Database object to set configuration options such as proto_descriptors. + * @param statements DDL statements to run while updating the database. + * @param operationId Operation id assigned to this operation. If null, system will autogenerate + * one. This must be unique within a database abd must be a valid identifier + * [a-zA-Z][a-zA-Z0-9_]*. + */ + OperationFuture updateDatabaseDdl( + Database database, Iterable statements, @Nullable String operationId) + throws SpannerException; + /** * Drops a Cloud Spanner database. * @@ -434,6 +469,23 @@ OperationFuture updateDatabaseDdl( */ List getDatabaseDdl(String instanceId, String databaseId); + /** + * Returns the GetDatabaseDdlResponse object of a Cloud Spanner database. + * + *

Example to get GetDatabaseDdlResponse object of a Cloud Spanner database. + * + *

{@code
+   * String instanceId = my_instance_id;
+   * String databaseId = my_database_id;
+   * GetDatabaseDdlResponse response = dbAdminClient.getDatabaseDdl(instanceId, databaseId);
+   * }
+ * + * @param instanceId the id of the instance where the database was created. + * @param databaseId the id of the database. + * @return GetDatabaseDdlResponse object + */ + GetDatabaseDdlResponse getDatabaseDdlResponse(String instanceId, String databaseId); + /** * Returns the list of Cloud Spanner database in the given instance. * diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java index 73ece214c3a..125aa74cad1 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java @@ -422,10 +422,20 @@ public OperationFuture updateDatabaseDdl( final Iterable statements, @Nullable String operationId) throws SpannerException { - final String dbName = getDatabaseName(instanceId, databaseId); + + return updateDatabaseDdl( + newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)).build(), + statements, + operationId); + } + + @Override + public OperationFuture updateDatabaseDdl( + Database database, final Iterable statements, @Nullable String operationId) + throws SpannerException { final String opId = operationId != null ? operationId : randomOperationId(); OperationFuture rawOperationFuture = - rpc.updateDatabaseDdl(dbName, statements, opId); + rpc.updateDatabaseDdl(database, statements, opId); return new OperationFutureImpl<>( rawOperationFuture.getPollingFuture(), rawOperationFuture.getInitialFuture(), @@ -447,6 +457,11 @@ public void dropDatabase(String instanceId, String databaseId) throws SpannerExc @Override public List getDatabaseDdl(String instanceId, String databaseId) { + return getDatabaseDdlResponse(instanceId, databaseId).getStatementsList(); + } + + @Override + public GetDatabaseDdlResponse getDatabaseDdlResponse(String instanceId, String databaseId) { String dbName = getDatabaseName(instanceId, databaseId); return rpc.getDatabaseDdl(dbName); } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseInfo.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseInfo.java index 565517e3419..b992b23b0dc 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseInfo.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseInfo.java @@ -19,7 +19,11 @@ import com.google.cloud.Timestamp; import com.google.cloud.spanner.encryption.CustomerManagedEncryption; import com.google.common.base.Preconditions; +import com.google.protobuf.ByteString; +import java.io.IOException; +import java.io.InputStream; import java.util.Objects; +import javax.annotation.Nonnull; import javax.annotation.Nullable; /** Represents a Cloud Spanner database. */ @@ -58,6 +62,34 @@ public Builder setDialect(Dialect dialect) { throw new UnsupportedOperationException("Unimplemented"); } + /** + * Optional for creating a new database. + * + *

It is used by CREATE/ALTER PROTO BUNDLE statements which are part of DDL statements. + * Contains a protobuf-serialized [google.protobuf.FileDescriptorSet]. To generate a proto + * descriptors file run {@code protoc --include_imports + * --descriptor_set_out=DESCRIPTOR_OUTPUT_LOCATION LOCATION-OF-PROTO-FILES} + * + * @param protoDescriptors The proto descriptors input as byte[] to be used for the database. + * @return {@link Builder} + */ + public abstract Builder setProtoDescriptors(@Nonnull byte[] protoDescriptors); + + /** + * Optional for creating a new database. + * + *

It is used by CREATE/ALTER PROTO BUNDLE statements which are part of DDL statements. + * Contains a protobuf-serialized [google.protobuf.FileDescriptorSet]. To generate a proto + * descriptors file run {@code protoc --include_imports + * --descriptor_set_out=DESCRIPTOR_OUTPUT_LOCATION LOCATION-OF-PROTO-FILES} + * + * @param inputStream The proto descriptors input as InputStream to be used for the database. + * @return {@link Builder} + * @throws IOException if there is a problem reading the underlying stream. + */ + public abstract Builder setProtoDescriptors(@Nonnull InputStream inputStream) + throws IOException; + abstract Builder setProto(com.google.spanner.admin.database.v1.Database proto); /** Builds the database from this builder. */ @@ -74,6 +106,7 @@ abstract static class BuilderImpl extends Builder { private CustomerManagedEncryption encryptionConfig; private String defaultLeader; private Dialect dialect = Dialect.GOOGLE_STANDARD_SQL; + private ByteString protoDescriptors; private com.google.spanner.admin.database.v1.Database proto; BuilderImpl(DatabaseId id) { @@ -90,6 +123,7 @@ abstract static class BuilderImpl extends Builder { this.encryptionConfig = other.encryptionConfig; this.defaultLeader = other.defaultLeader; this.dialect = other.dialect; + this.protoDescriptors = other.protoDescriptors; this.proto = other.proto; } @@ -141,6 +175,20 @@ public Builder setDialect(Dialect dialect) { return this; } + @Override + public Builder setProtoDescriptors(@Nonnull byte[] protoDescriptors) { + Preconditions.checkNotNull(protoDescriptors); + this.protoDescriptors = ByteString.copyFrom(protoDescriptors); + return this; + } + + @Override + public Builder setProtoDescriptors(@Nonnull InputStream inputStream) throws IOException { + Preconditions.checkNotNull(inputStream); + this.protoDescriptors = ByteString.readFrom(inputStream); + return this; + } + @Override Builder setProto(@Nullable com.google.spanner.admin.database.v1.Database proto) { this.proto = proto; @@ -169,6 +217,7 @@ public enum State { private final CustomerManagedEncryption encryptionConfig; private final String defaultLeader; private final Dialect dialect; + private final ByteString protoDescriptors; private final com.google.spanner.admin.database.v1.Database proto; public DatabaseInfo(DatabaseId id, State state) { @@ -181,6 +230,7 @@ public DatabaseInfo(DatabaseId id, State state) { this.encryptionConfig = null; this.defaultLeader = null; this.dialect = null; + this.protoDescriptors = null; this.proto = null; } @@ -194,6 +244,7 @@ public DatabaseInfo(DatabaseId id, State state) { this.encryptionConfig = builder.encryptionConfig; this.defaultLeader = builder.defaultLeader; this.dialect = builder.dialect; + this.protoDescriptors = builder.protoDescriptors; this.proto = builder.proto; } @@ -262,6 +313,10 @@ public Timestamp getEarliestVersionTime() { return dialect; } + public ByteString getProtoDescriptors() { + return protoDescriptors; + } + /** Returns the raw proto instance that was used to construct this {@link Database}. */ public @Nullable com.google.spanner.admin.database.v1.Database getProto() { return proto; @@ -284,7 +339,8 @@ public boolean equals(Object o) { && Objects.equals(earliestVersionTime, that.earliestVersionTime) && Objects.equals(encryptionConfig, that.encryptionConfig) && Objects.equals(defaultLeader, that.defaultLeader) - && Objects.equals(dialect, that.dialect); + && Objects.equals(dialect, that.dialect) + && Objects.equals(protoDescriptors, that.protoDescriptors); } @Override @@ -298,13 +354,14 @@ public int hashCode() { earliestVersionTime, encryptionConfig, defaultLeader, - dialect); + dialect, + protoDescriptors); } @Override public String toString() { return String.format( - "Database[%s, %s, %s, %s, %s, %s, %s, %s, %s]", + "Database[%s, %s, %s, %s, %s, %s, %s, %s, %s, %s]", id.getName(), state, createTime, @@ -313,6 +370,7 @@ public String toString() { earliestVersionTime, encryptionConfig, defaultLeader, - dialect); + dialect, + protoDescriptors); } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClient.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClient.java index d625748b5e8..6325f020c89 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClient.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClient.java @@ -525,6 +525,7 @@ public final OperationFuture createDatabaseAsy * .addAllExtraStatements(new ArrayList()) * .setEncryptionConfig(EncryptionConfig.newBuilder().build()) * .setDatabaseDialect(DatabaseDialect.forNumber(0)) + * .setProtoDescriptors(ByteString.EMPTY) * .build(); * Database response = databaseAdminClient.createDatabaseAsync(request).get(); * } @@ -564,6 +565,7 @@ public final OperationFuture createDatabaseAsy * .addAllExtraStatements(new ArrayList()) * .setEncryptionConfig(EncryptionConfig.newBuilder().build()) * .setDatabaseDialect(DatabaseDialect.forNumber(0)) + * .setProtoDescriptors(ByteString.EMPTY) * .build(); * OperationFuture future = * databaseAdminClient.createDatabaseOperationCallable().futureCall(request); @@ -603,6 +605,7 @@ public final OperationFuture createDatabaseAsy * .addAllExtraStatements(new ArrayList()) * .setEncryptionConfig(EncryptionConfig.newBuilder().build()) * .setDatabaseDialect(DatabaseDialect.forNumber(0)) + * .setProtoDescriptors(ByteString.EMPTY) * .build(); * ApiFuture future = * databaseAdminClient.createDatabaseCallable().futureCall(request); @@ -827,6 +830,7 @@ public final OperationFuture updateDatabaseDdl * .setDatabase(DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]").toString()) * .addAllStatements(new ArrayList()) * .setOperationId("operationId129704162") + * .setProtoDescriptors(ByteString.EMPTY) * .build(); * databaseAdminClient.updateDatabaseDdlAsync(request).get(); * } @@ -864,6 +868,7 @@ public final OperationFuture updateDatabaseDdl * .setDatabase(DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]").toString()) * .addAllStatements(new ArrayList()) * .setOperationId("operationId129704162") + * .setProtoDescriptors(ByteString.EMPTY) * .build(); * OperationFuture future = * databaseAdminClient.updateDatabaseDdlOperationCallable().futureCall(request); @@ -901,6 +906,7 @@ public final OperationFuture updateDatabaseDdl * .setDatabase(DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]").toString()) * .addAllStatements(new ArrayList()) * .setOperationId("operationId129704162") + * .setProtoDescriptors(ByteString.EMPTY) * .build(); * ApiFuture future = * databaseAdminClient.updateDatabaseDdlCallable().futureCall(request); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java index 7f325665542..9ccad743034 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java @@ -117,6 +117,7 @@ import com.google.spanner.admin.database.v1.DropDatabaseRequest; import com.google.spanner.admin.database.v1.GetBackupRequest; import com.google.spanner.admin.database.v1.GetDatabaseDdlRequest; +import com.google.spanner.admin.database.v1.GetDatabaseDdlResponse; import com.google.spanner.admin.database.v1.GetDatabaseRequest; import com.google.spanner.admin.database.v1.ListBackupOperationsRequest; import com.google.spanner.admin.database.v1.ListBackupOperationsResponse; @@ -1190,8 +1191,10 @@ public OperationFuture createDatabase( if (databaseInfo.getDialect() != null) { requestBuilder.setDatabaseDialect(databaseInfo.getDialect().toProto()); } + if (databaseInfo.getProtoDescriptors() != null) { + requestBuilder.setProtoDescriptors(databaseInfo.getProtoDescriptors()); + } final CreateDatabaseRequest request = requestBuilder.build(); - OperationFutureCallable callable = new OperationFutureCallable<>( databaseAdminStub.createDatabaseOperationCallable(), @@ -1246,19 +1249,27 @@ public OperationFuture createDatabase( */ @Override public OperationFuture updateDatabaseDdl( - final String databaseName, + com.google.cloud.spanner.Database databaseInfo, final Iterable updateDatabaseStatements, @Nullable final String updateId) throws SpannerException { acquireAdministrativeRequestsRateLimiter(); - final UpdateDatabaseDdlRequest request = + Preconditions.checkNotNull(databaseInfo.getId()); + UpdateDatabaseDdlRequest.Builder requestBuilder = UpdateDatabaseDdlRequest.newBuilder() - .setDatabase(databaseName) + .setDatabase(databaseInfo.getId().getName()) .addAllStatements(updateDatabaseStatements) - .setOperationId(MoreObjects.firstNonNull(updateId, "")) - .build(); + .setOperationId(MoreObjects.firstNonNull(updateId, "")); + if (databaseInfo.getProtoDescriptors() != null) { + requestBuilder.setProtoDescriptors(databaseInfo.getProtoDescriptors()); + } + final UpdateDatabaseDdlRequest request = requestBuilder.build(); final GrpcCallContext context = - newCallContext(null, databaseName, request, DatabaseAdminGrpc.getUpdateDatabaseDdlMethod()); + newCallContext( + null, + databaseInfo.getId().getName(), + request, + DatabaseAdminGrpc.getUpdateDatabaseDdlMethod()); final OperationCallable callable = databaseAdminStub.updateDatabaseDdlOperationCallable(); @@ -1280,7 +1291,7 @@ public OperationFuture updateDatabaseDdl( if (t instanceof AlreadyExistsException) { String operationName = OPERATION_NAME_TEMPLATE.instantiate( - "database", databaseName, "operation", updateId); + "database", databaseInfo.getId().getName(), "operation", updateId); return callable.resumeFutureCall(operationName, context); } } @@ -1316,7 +1327,7 @@ public Database getDatabase(String databaseName) throws SpannerException { } @Override - public List getDatabaseDdl(String databaseName) throws SpannerException { + public GetDatabaseDdlResponse getDatabaseDdl(String databaseName) throws SpannerException { acquireAdministrativeRequestsRateLimiter(); final GetDatabaseDdlRequest request = GetDatabaseDdlRequest.newBuilder().setDatabase(databaseName).build(); @@ -1324,9 +1335,7 @@ public List getDatabaseDdl(String databaseName) throws SpannerException final GrpcCallContext context = newCallContext(null, databaseName, request, DatabaseAdminGrpc.getGetDatabaseDdlMethod()); return runWithRetryOnAdministrativeRequestsExceeded( - () -> - get(databaseAdminStub.getDatabaseDdlCallable().futureCall(request, context)) - .getStatementsList()); + () -> get(databaseAdminStub.getDatabaseDdlCallable().futureCall(request, context))); } @Override diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java index 2f68b9c1df2..e566057929d 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java @@ -40,6 +40,7 @@ import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; import com.google.spanner.admin.database.v1.Database; import com.google.spanner.admin.database.v1.DatabaseRole; +import com.google.spanner.admin.database.v1.GetDatabaseDdlResponse; import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import com.google.spanner.admin.instance.v1.CreateInstanceConfigMetadata; @@ -148,7 +149,6 @@ interface ResultStreamConsumer { /** Handle for cancellation of a streaming read or query call. */ interface StreamingCall { - /** * Requests more messages from the stream. We disable the auto flow control mechanism in grpc, * so we need to request messages ourself. This gives us more control over how much buffer we @@ -225,14 +225,17 @@ OperationFuture createDatabase( throws SpannerException; OperationFuture updateDatabaseDdl( - String databaseName, Iterable updateDatabaseStatements, @Nullable String updateId) + com.google.cloud.spanner.Database database, + Iterable updateDatabaseStatements, + @Nullable String updateId) throws SpannerException; void dropDatabase(String databaseName) throws SpannerException; Database getDatabase(String databaseName) throws SpannerException; - List getDatabaseDdl(String databaseName) throws SpannerException; + GetDatabaseDdlResponse getDatabaseDdl(String databaseName) throws SpannerException; + /** Lists the backups in the specified instance. */ Paginated listBackups( String instanceName, int pageSize, @Nullable String filter, @Nullable String pageToken) diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java index 0255f6c1668..8a9144b0be6 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java @@ -51,6 +51,7 @@ import com.google.spanner.admin.database.v1.DatabaseDialect; import com.google.spanner.admin.database.v1.DatabaseRole; import com.google.spanner.admin.database.v1.EncryptionInfo; +import com.google.spanner.admin.database.v1.GetDatabaseDdlResponse; import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.ArrayList; @@ -222,7 +223,9 @@ public void updateDatabaseDdl() throws Exception { OperationFuture rawOperationFuture = OperationFutureUtil.immediateOperationFuture( opName, Empty.getDefaultInstance(), UpdateDatabaseDdlMetadata.getDefaultInstance()); - when(rpc.updateDatabaseDdl(DB_NAME, ddl, opId)).thenReturn(rawOperationFuture); + when(rpc.updateDatabaseDdl( + client.newDatabaseBuilder(DatabaseId.of(DB_NAME)).build(), ddl, opId)) + .thenReturn(rawOperationFuture); OperationFuture op = client.updateDatabaseDdl(INSTANCE_ID, DB_ID, ddl, opId); assertThat(op.isDone()).isTrue(); @@ -240,7 +243,9 @@ public void updateDatabaseDdlOpAlreadyExists() throws Exception { UpdateDatabaseDdlMetadata.getDefaultInstance()); String newOpId = "newop"; - when(rpc.updateDatabaseDdl(DB_NAME, ddl, newOpId)).thenReturn(originalOp); + when(rpc.updateDatabaseDdl( + client.newDatabaseBuilder(DatabaseId.of(DB_NAME)).build(), ddl, newOpId)) + .thenReturn(originalOp); OperationFuture op = client.updateDatabaseDdl(INSTANCE_ID, DB_ID, ddl, newOpId); assertThat(op.getName()).isEqualTo(originalOpName); @@ -255,10 +260,25 @@ public void dropDatabase() { @Test public void getDatabaseDdl() { List ddl = ImmutableList.of("CREATE TABLE mytable()"); - when(rpc.getDatabaseDdl(DB_NAME)).thenReturn(ddl); + when(rpc.getDatabaseDdl(DB_NAME)) + .thenReturn(GetDatabaseDdlResponse.newBuilder().addAllStatements(ddl).build()); assertThat(client.getDatabaseDdl(INSTANCE_ID, DB_ID)).isEqualTo(ddl); } + @Test + public void getDatabaseDdlResponse() { + List ddl = ImmutableList.of("CREATE TABLE mytable()"); + when(rpc.getDatabaseDdl(DB_NAME)) + .thenReturn( + GetDatabaseDdlResponse.newBuilder() + .addAllStatements(ddl) + .setProtoDescriptors(ByteString.EMPTY) + .build()); + GetDatabaseDdlResponse response = client.getDatabaseDdlResponse(INSTANCE_ID, DB_ID); + assertThat(response.getStatementsList()).isEqualTo(ddl); + assertThat(response.getProtoDescriptors()).isEqualTo(ByteString.EMPTY); + } + @Test public void listDatabases() { String pageToken = "token"; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java index 1eb2794c8ee..ad799485a1b 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java @@ -19,6 +19,7 @@ import static com.google.cloud.spanner.DatabaseInfo.State.CREATING; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -30,10 +31,14 @@ import com.google.cloud.Timestamp; import com.google.cloud.spanner.DatabaseInfo.State; import com.google.cloud.spanner.encryption.EncryptionConfigs; +import com.google.common.io.ByteStreams; +import com.google.protobuf.ByteString; import com.google.rpc.Code; import com.google.rpc.Status; import com.google.spanner.admin.database.v1.DatabaseDialect; import com.google.spanner.admin.database.v1.EncryptionInfo; +import java.io.IOException; +import java.io.InputStream; import java.util.Collections; import java.util.List; import org.junit.Before; @@ -66,6 +71,10 @@ public class DatabaseTest { .build()); private static final String DEFAULT_LEADER = "default-leader"; private static final DatabaseDialect DEFAULT_DIALECT = DatabaseDialect.GOOGLE_STANDARD_SQL; + private static ByteString protoDescriptors; + private static byte[] protoDescriptorsByteArray; + private static final String PROTO_DESCRIPTORS_RESOURCE_PATH = + "com/google/cloud/spanner/descriptors.pb"; @Mock DatabaseAdminClient dbClient; @@ -79,6 +88,15 @@ public void setUp() { .thenAnswer( invocation -> new Database.Builder(dbClient, (DatabaseId) invocation.getArguments()[0])); + try { + InputStream protoDescriptorsInputStream = + getClass().getClassLoader().getResourceAsStream(PROTO_DESCRIPTORS_RESOURCE_PATH); + assertNotNull(protoDescriptorsInputStream); + protoDescriptorsByteArray = ByteStreams.toByteArray(protoDescriptorsInputStream); + protoDescriptors = ByteString.copyFrom(protoDescriptorsByteArray); + } catch (IOException e) { + e.printStackTrace(); + } } @Test @@ -178,6 +196,46 @@ public void testBuildWithDatabaseDialect() { assertEquals(Dialect.GOOGLE_STANDARD_SQL, database.getDialect()); } + @Test + public void testBuildWithProtoDescriptorsFromInputStream() throws IOException { + InputStream in = + getClass().getClassLoader().getResourceAsStream(PROTO_DESCRIPTORS_RESOURCE_PATH); + assertNotNull(in); + final Database database = + dbClient + .newDatabaseBuilder(DatabaseId.of("my-project", "my-instance", "my-database")) + .setProtoDescriptors(in) + .build(); + + assertEquals(protoDescriptors, database.getProtoDescriptors()); + } + + @Test + public void testBuildWithProtoDescriptorsFromByteArray() { + final Database database = + dbClient + .newDatabaseBuilder(DatabaseId.of("my-project", "my-instance", "my-database")) + .setProtoDescriptors(protoDescriptorsByteArray) + .build(); + + assertEquals(protoDescriptors, database.getProtoDescriptors()); + } + + @Test + public void testBuildWithProtoDescriptorsThrowsException() throws IOException { + InputStream in = + getClass().getClassLoader().getResourceAsStream(PROTO_DESCRIPTORS_RESOURCE_PATH); + in.close(); + // case1: Test one of the IOException case, where InputStream is closed before read + assertThrows( + IOException.class, + () -> + dbClient + .newDatabaseBuilder(DatabaseId.of("my-project", "my-instance", "my-database")) + .setProtoDescriptors(in) + .build()); + } + @Test public void getIAMPolicy() { Database database = diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientHttpJsonTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientHttpJsonTest.java index 31e6d9d97fb..1cbcb3d6d83 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientHttpJsonTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientHttpJsonTest.java @@ -607,7 +607,10 @@ public void dropDatabaseExceptionTest2() throws Exception { @Test public void getDatabaseDdlTest() throws Exception { GetDatabaseDdlResponse expectedResponse = - GetDatabaseDdlResponse.newBuilder().addAllStatements(new ArrayList()).build(); + GetDatabaseDdlResponse.newBuilder() + .addAllStatements(new ArrayList()) + .setProtoDescriptors(ByteString.EMPTY) + .build(); mockService.addResponse(expectedResponse); DatabaseName database = DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]"); @@ -649,7 +652,10 @@ public void getDatabaseDdlExceptionTest() throws Exception { @Test public void getDatabaseDdlTest2() throws Exception { GetDatabaseDdlResponse expectedResponse = - GetDatabaseDdlResponse.newBuilder().addAllStatements(new ArrayList()).build(); + GetDatabaseDdlResponse.newBuilder() + .addAllStatements(new ArrayList()) + .setProtoDescriptors(ByteString.EMPTY) + .build(); mockService.addResponse(expectedResponse); String database = "projects/project-3102/instances/instance-3102/databases/database-3102"; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientTest.java index 51c780c9829..bbea144499f 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientTest.java @@ -586,7 +586,10 @@ public void dropDatabaseExceptionTest2() throws Exception { @Test public void getDatabaseDdlTest() throws Exception { GetDatabaseDdlResponse expectedResponse = - GetDatabaseDdlResponse.newBuilder().addAllStatements(new ArrayList()).build(); + GetDatabaseDdlResponse.newBuilder() + .addAllStatements(new ArrayList()) + .setProtoDescriptors(ByteString.EMPTY) + .build(); mockDatabaseAdmin.addResponse(expectedResponse); DatabaseName database = DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]"); @@ -622,7 +625,10 @@ public void getDatabaseDdlExceptionTest() throws Exception { @Test public void getDatabaseDdlTest2() throws Exception { GetDatabaseDdlResponse expectedResponse = - GetDatabaseDdlResponse.newBuilder().addAllStatements(new ArrayList()).build(); + GetDatabaseDdlResponse.newBuilder() + .addAllStatements(new ArrayList()) + .setProtoDescriptors(ByteString.EMPTY) + .build(); mockDatabaseAdmin.addResponse(expectedResponse); String database = "database1789464955"; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITProtoColumnTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITProtoColumnTest.java index 7d689612284..cbe00c1db4d 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITProtoColumnTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITProtoColumnTest.java @@ -21,8 +21,11 @@ import static org.junit.Assume.assumeFalse; import com.google.cloud.ByteArray; +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.IntegrationTestEnv; import com.google.cloud.spanner.Key; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; @@ -30,52 +33,112 @@ import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SingerProto.Genre; import com.google.cloud.spanner.SingerProto.SingerInfo; -import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; +import com.google.cloud.spanner.testing.RemoteSpannerHelper; import com.google.common.collect.ImmutableList; import com.google.protobuf.AbstractMessage; import com.google.protobuf.InvalidProtocolBufferException.InvalidWireTypeException; import com.google.protobuf.ProtocolMessageEnum; import com.google.spanner.admin.database.v1.Backup; +import java.io.InputStream; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.concurrent.TimeUnit; import org.junit.After; +import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Integrations Tests to test Proto Columns & Enums */ +// Integration Tests to test DDL, DML and DQL for Proto Columns & Enums +// TODO(harsha): Check session leak warning @Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITProtoColumnTest { - private static String projectId; - private static String instanceId; - private static String databaseId; + + @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + private static DatabaseId databaseID; + private static DatabaseAdminClient dbAdminClient; private static DatabaseClient databaseClient; @BeforeClass - public static void beforeClass() throws Exception { - assumeFalse( - "Proto Column is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); - // ToDo: Update project, instance and database parameter before GA - projectId = "span-cloud-testing"; - databaseId = "int_test_proto_column_db"; - instanceId = "integration-test-proto-column"; - - Spanner spanner = - SpannerOptions.newBuilder() - .setHost("https://staging-wrenchworks.sandbox.googleapis.com") - .setProjectId(projectId) - .build() - .getService(); - - databaseClient = spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); + public static void setUpDatabase() throws Exception { + RemoteSpannerHelper testHelper = env.getTestHelper(); + databaseID = DatabaseId.of(testHelper.getInstanceId(), testHelper.getUniqueDatabaseId()); + dbAdminClient = testHelper.getClient().getDatabaseAdminClient(); + createDatabase(); + databaseClient = testHelper.getClient().getDatabaseClient(databaseID); + } + + public static void createDatabase() throws Exception { + InputStream in = + ITProtoColumnTest.class + .getClassLoader() + .getResourceAsStream("com/google/cloud/spanner/descriptors.pb"); + final Database databaseToCreate = + dbAdminClient.newDatabaseBuilder(databaseID).setProtoDescriptors(in).build(); + final Database createdDatabase = + dbAdminClient + .createDatabase( + databaseToCreate, + Arrays.asList( + "CREATE PROTO BUNDLE (" + + "spanner.examples.music.SingerInfo," + + "spanner.examples.music.Genre," + + ")", + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo spanner.examples.music.SingerInfo," + + " SingerGenre spanner.examples.music.Genre," + + " SingerNationality STRING(1024) AS (SingerInfo.nationality) STORED," + + " ) PRIMARY KEY (SingerNationality, SingerGenre)", + "CREATE TABLE Types (" + + " RowID INT64 NOT NULL," + + " Int64a INT64," + + " Bytes BYTES(MAX)," + + " Int64Array ARRAY," + + " BytesArray ARRAY," + + " ProtoMessage spanner.examples.music.SingerInfo," + + " ProtoEnum spanner.examples.music.Genre," + + " ProtoMessageArray ARRAY," + + " ProtoEnumArray ARRAY," + + " ) PRIMARY KEY (RowID)", + "CREATE INDEX SingerByNationalityAndGenre ON Singers(SingerNationality, SingerGenre)" + + " STORING (SingerId, FirstName, LastName)")) + .get(5, TimeUnit.MINUTES); + + assertEquals(databaseID.getDatabase(), createdDatabase.getId().getDatabase()); + + // TODO(harsha): Check with backend team as this is not working for generated columns yet. + // GetDatabaseDdlResponse response = + // dbAdminClient.getDatabaseDdlResponse(databaseID.getInstanceId().getInstance(), + // databaseID.getDatabase()); + // assertNotNull(response.getProtoDescriptors()); + in.close(); + } + + @AfterClass + public static void afterClass() throws Exception { + try { + dbAdminClient.dropDatabase( + databaseID.getInstanceId().getInstance(), databaseID.getDatabase()); + } catch (Exception e) { + System.err.println( + "Failed to drop database " + + dbAdminClient + .getDatabase(databaseID.getInstanceId().getInstance(), databaseID.getDatabase()) + .getId() + + ", skipping...: " + + e.getMessage()); + } } @After @@ -85,23 +148,16 @@ public void after() throws Exception { } /** - * Test to check updates and read queries on Proto column and Enums and their arrays. Test also - * checks for compatability between following types: 1. Proto Messages & Bytes 2. Proto Enums & - * Int64 - * - *

Table `Types` was created through gcloud using following DDL: - * ************************************** CREATE TABLE Types ( RowID INT64 NOT NULL, Int64a INT64, - * Bytes BYTES(MAX), Int64Array ARRAY, BytesArray ARRAY, ProtoMessage - * spanner.examples.music.SingerInfo, ProtoEnum spanner.examples.music.Genre, ProtoMessageArray - * ARRAY, ProtoEnumArray ARRAY, ) - * PRIMARY KEY (RowID); ************************************** + * Test to check data update and read queries on Proto Messages, Proto Enums and their arrays. + * Test also checks for compatability between following types: 1. Proto Messages & Bytes 2. Proto + * Enums & Int64 */ @Test - public void testProtoUpdateAndRead() { + public void testProtoColumnsUpdateAndRead() { assumeFalse( "Proto Column is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); SingerInfo singerInfo = - SingerInfo.newBuilder().setSingerId(11).setNationality("Country1").build(); + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); ByteArray singerInfoBytes = ByteArray.copyFrom(singerInfo.toByteArray()); Genre genre = Genre.JAZZ; @@ -124,7 +180,7 @@ public void testProtoUpdateAndRead() { ImmutableList.of( Mutation.newInsertOrUpdateBuilder("Types") .set("RowID") - .to(11) + .to(1) .set("Int64a") .to(genreConst) .set("Bytes") @@ -142,10 +198,10 @@ public void testProtoUpdateAndRead() { .set("ProtoEnumArray") .toProtoEnumArray(enumList, Genre.getDescriptor()) .build(), - //Inter Compatability check between ProtoMessages/Bytes and Int64/Enum. + // Inter Compatability check between ProtoMessages/Bytes and Int64/Enum. Mutation.newInsertOrUpdateBuilder("Types") .set("RowID") - .to(12) + .to(2) .set("Int64a") .to(genre) .set("Bytes") @@ -167,9 +223,9 @@ public void testProtoUpdateAndRead() { try (ResultSet resultSet = databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + "Types"))) { - for(int i=0;i<2;i++) { + for (int i = 0; i < 2; i++) { resultSet.next(); - assertEquals(11 + i, resultSet.getLong("RowID")); + assertEquals(i + 1, resultSet.getLong("RowID")); assertEquals(genreConst, resultSet.getLong("Int64a")); assertEquals(singerInfoBytes, resultSet.getBytes("Bytes")); assertEquals(enumConstList, resultSet.getLongList("Int64Array")); @@ -184,7 +240,8 @@ public void testProtoUpdateAndRead() { // Check compatability between Proto Messages & Bytes assertEquals(singerInfoBytes, resultSet.getBytes("ProtoMessage")); - assertEquals(singerInfo, resultSet.getProtoMessage("Bytes", SingerInfo.getDefaultInstance())); + assertEquals( + singerInfo, resultSet.getProtoMessage("Bytes", SingerInfo.getDefaultInstance())); assertEquals(singerInfoBytesList, resultSet.getBytesList("ProtoMessageArray")); assertEquals( @@ -201,31 +258,18 @@ public void testProtoUpdateAndRead() { } } - /** - * Test to check Parameterized Queries, Primary Keys and Indexes. - * - *

Table `Singers` and Index `SingerByNationalityAndGenre` for Proto column integration tests - * is created through gcloud using following DDL: - * - *

************************************** CREATE TABLE Singers ( SingerId INT64 NOT NULL, - * FirstName STRING(1024), LastName STRING(1024), SingerInfo spanner.examples.music.SingerInfo, - * SingerGenre spanner.examples.music.Genre, SingerNationality STRING(1024) AS - * (SingerInfo.nationality) STORED, ) PRIMARY KEY (SingerNationality, SingerGenre); - * - *

CREATE INDEX SingerByNationalityAndGenre ON Singers(SingerNationality, SingerGenre) STORING - * (SingerId, FirstName, LastName); ************************************** - */ + // Test to check Parameterized Queries, Primary Keys and Indexes. @Test - public void testProtoColumnsDMLParameterizedQueriesAndPKIndexes() { + public void testProtoColumnsDMLParameterizedQueriesPKAndIndexes() { assumeFalse( "Proto Column is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); SingerInfo singerInfo1 = - SingerInfo.newBuilder().setSingerId(11).setNationality("Country1").build(); + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); Genre genre1 = Genre.FOLK; SingerInfo singerInfo2 = - SingerInfo.newBuilder().setSingerId(11).setNationality("Country2").build(); + SingerInfo.newBuilder().setSingerId(2).setNationality("Country2").build(); Genre genre2 = Genre.JAZZ; databaseClient @@ -234,7 +278,7 @@ public void testProtoColumnsDMLParameterizedQueriesAndPKIndexes() { transaction -> { Statement statement1 = Statement.newBuilder( - "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, SingerGenre) VALUES (11, \"FirstName1\", \"LastName1\", @singerInfo, @singerGenre)") + "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, SingerGenre) VALUES (1, \"FirstName1\", \"LastName1\", @singerInfo, @singerGenre)") .bind("singerInfo") .to(singerInfo1) .bind("singerGenre") @@ -243,7 +287,7 @@ public void testProtoColumnsDMLParameterizedQueriesAndPKIndexes() { Statement statement2 = Statement.newBuilder( - "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, SingerGenre) VALUES (22, \"FirstName2\", \"LastName2\", @singerInfo, @singerGenre)") + "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, SingerGenre) VALUES (2, \"FirstName2\", \"LastName2\", @singerInfo, @singerGenre)") .bind("singerInfo") .to(singerInfo2) .bind("singerGenre") @@ -267,7 +311,7 @@ public void testProtoColumnsDMLParameterizedQueriesAndPKIndexes() { Arrays.asList("SingerId", "FirstName", "LastName", "SingerInfo", "SingerGenre")); resultSet1.next(); - assertEquals(11, resultSet1.getLong("SingerId")); + assertEquals(1, resultSet1.getLong("SingerId")); assertEquals("FirstName1", resultSet1.getString("FirstName")); assertEquals("LastName1", resultSet1.getString("LastName")); assertEquals( @@ -275,7 +319,7 @@ public void testProtoColumnsDMLParameterizedQueriesAndPKIndexes() { assertEquals(genre1, resultSet1.getProtoEnum("SingerGenre", Genre::forNumber)); resultSet1.next(); - assertEquals(22, resultSet1.getLong("SingerId")); + assertEquals(2, resultSet1.getLong("SingerId")); assertEquals("FirstName2", resultSet1.getString("FirstName")); assertEquals("LastName2", resultSet1.getString("LastName")); assertEquals( @@ -292,7 +336,7 @@ public void testProtoColumnsDMLParameterizedQueriesAndPKIndexes() { KeySet.singleKey(Key.of("Country2", Genre.JAZZ)), Arrays.asList("SingerId", "FirstName", "LastName")); resultSet2.next(); - assertEquals(22, resultSet2.getLong("SingerId")); + assertEquals(2, resultSet2.getLong("SingerId")); assertEquals("FirstName2", resultSet2.getString("FirstName")); assertEquals("LastName2", resultSet2.getString("LastName")); @@ -311,29 +355,27 @@ public void testProtoColumnsDMLParameterizedQueriesAndPKIndexes() { .build()); resultSet3.next(); - assertEquals(22, resultSet1.getLong("SingerId")); + assertEquals(2, resultSet1.getLong("SingerId")); assertEquals( singerInfo2, resultSet1.getProtoMessage("SingerInfo", SingerInfo.getDefaultInstance())); assertEquals(genre2, resultSet1.getProtoEnum("SingerGenre", Genre::forNumber)); } - /** - * Test the exception in case Invalid protocol message object is provided while deserializing the - * data. - */ + // Test the exception in case Invalid protocol message object is provided while deserializing the + // data. @Test public void testProtoMessageDeserializationError() { assumeFalse( "Proto Column is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); SingerInfo singerInfo = - SingerInfo.newBuilder().setSingerId(11).setNationality("Country1").build(); + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); databaseClient.write( ImmutableList.of( Mutation.newInsertOrUpdateBuilder("Types") .set("RowID") - .to(11) + .to(1) .set("ProtoMessage") .to(singerInfo) .build())); diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/descriptors.pb b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/descriptors.pb new file mode 100644 index 00000000000..3ebb79420b3 Binary files /dev/null and b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/descriptors.pb differ diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/CreateDatabaseRequest.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/CreateDatabaseRequest.java index 067490d01b5..2b2b510e56e 100644 --- a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/CreateDatabaseRequest.java +++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/CreateDatabaseRequest.java @@ -42,6 +42,7 @@ private CreateDatabaseRequest() { createStatement_ = ""; extraStatements_ = com.google.protobuf.LazyStringArrayList.EMPTY; databaseDialect_ = 0; + protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; } @java.lang.Override @@ -358,6 +359,38 @@ public com.google.spanner.admin.database.v1.DatabaseDialect getDatabaseDialect() : result; } + public static final int PROTO_DESCRIPTORS_FIELD_NUMBER = 6; + private com.google.protobuf.ByteString protoDescriptors_; + /** + * + * + *

+   * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements in
+   * 'extra_statements' above.
+   * Contains a protobuf-serialized
+   * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+   * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+   * run `protoc` with --include_imports and --descriptor_set_out. For example,
+   * to generate for moon/shot/app.proto, run
+   * """
+   * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+   *          --include_imports \
+   *          --descriptor_set_out=descriptors.data \
+   *          moon/shot/app.proto
+   * """
+   * For more details, see protobuffer [self
+   * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+   * 
+ * + * bytes proto_descriptors = 6 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The protoDescriptors. + */ + @java.lang.Override + public com.google.protobuf.ByteString getProtoDescriptors() { + return protoDescriptors_; + } + private byte memoizedIsInitialized = -1; @java.lang.Override @@ -389,6 +422,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io .getNumber()) { output.writeEnum(5, databaseDialect_); } + if (!protoDescriptors_.isEmpty()) { + output.writeBytes(6, protoDescriptors_); + } getUnknownFields().writeTo(output); } @@ -420,6 +456,9 @@ public int getSerializedSize() { .getNumber()) { size += com.google.protobuf.CodedOutputStream.computeEnumSize(5, databaseDialect_); } + if (!protoDescriptors_.isEmpty()) { + size += com.google.protobuf.CodedOutputStream.computeBytesSize(6, protoDescriptors_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -444,6 +483,7 @@ public boolean equals(final java.lang.Object obj) { if (!getEncryptionConfig().equals(other.getEncryptionConfig())) return false; } if (databaseDialect_ != other.databaseDialect_) return false; + if (!getProtoDescriptors().equals(other.getProtoDescriptors())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -469,6 +509,8 @@ public int hashCode() { } hash = (37 * hash) + DATABASE_DIALECT_FIELD_NUMBER; hash = (53 * hash) + databaseDialect_; + hash = (37 * hash) + PROTO_DESCRIPTORS_FIELD_NUMBER; + hash = (53 * hash) + getProtoDescriptors().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -622,6 +664,8 @@ public Builder clear() { } databaseDialect_ = 0; + protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; + return this; } @@ -663,6 +707,7 @@ public com.google.spanner.admin.database.v1.CreateDatabaseRequest buildPartial() result.encryptionConfig_ = encryptionConfigBuilder_.build(); } result.databaseDialect_ = databaseDialect_; + result.protoDescriptors_ = protoDescriptors_; onBuilt(); return result; } @@ -737,6 +782,9 @@ public Builder mergeFrom(com.google.spanner.admin.database.v1.CreateDatabaseRequ if (other.databaseDialect_ != 0) { setDatabaseDialectValue(other.getDatabaseDialectValue()); } + if (other.getProtoDescriptors() != com.google.protobuf.ByteString.EMPTY) { + setProtoDescriptors(other.getProtoDescriptors()); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -795,6 +843,12 @@ public Builder mergeFrom( break; } // case 40 + case 50: + { + protoDescriptors_ = input.readBytes(); + + break; + } // case 50 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { @@ -1585,6 +1639,103 @@ public Builder clearDatabaseDialect() { return this; } + private com.google.protobuf.ByteString protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; + /** + * + * + *
+     * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements in
+     * 'extra_statements' above.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+     * run `protoc` with --include_imports and --descriptor_set_out. For example,
+     * to generate for moon/shot/app.proto, run
+     * """
+     * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+     *          --include_imports \
+     *          --descriptor_set_out=descriptors.data \
+     *          moon/shot/app.proto
+     * """
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * 
+ * + * bytes proto_descriptors = 6 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The protoDescriptors. + */ + @java.lang.Override + public com.google.protobuf.ByteString getProtoDescriptors() { + return protoDescriptors_; + } + /** + * + * + *
+     * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements in
+     * 'extra_statements' above.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+     * run `protoc` with --include_imports and --descriptor_set_out. For example,
+     * to generate for moon/shot/app.proto, run
+     * """
+     * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+     *          --include_imports \
+     *          --descriptor_set_out=descriptors.data \
+     *          moon/shot/app.proto
+     * """
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * 
+ * + * bytes proto_descriptors = 6 [(.google.api.field_behavior) = OPTIONAL]; + * + * @param value The protoDescriptors to set. + * @return This builder for chaining. + */ + public Builder setProtoDescriptors(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + + protoDescriptors_ = value; + onChanged(); + return this; + } + /** + * + * + *
+     * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements in
+     * 'extra_statements' above.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+     * run `protoc` with --include_imports and --descriptor_set_out. For example,
+     * to generate for moon/shot/app.proto, run
+     * """
+     * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+     *          --include_imports \
+     *          --descriptor_set_out=descriptors.data \
+     *          moon/shot/app.proto
+     * """
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * 
+ * + * bytes proto_descriptors = 6 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return This builder for chaining. + */ + public Builder clearProtoDescriptors() { + + protoDescriptors_ = getDefaultInstance().getProtoDescriptors(); + onChanged(); + return this; + } + @java.lang.Override public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { return super.setUnknownFields(unknownFields); diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/CreateDatabaseRequestOrBuilder.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/CreateDatabaseRequestOrBuilder.java index 537e9c161fa..f9699e13d91 100644 --- a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/CreateDatabaseRequestOrBuilder.java +++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/CreateDatabaseRequestOrBuilder.java @@ -225,4 +225,31 @@ public interface CreateDatabaseRequestOrBuilder * @return The databaseDialect. */ com.google.spanner.admin.database.v1.DatabaseDialect getDatabaseDialect(); + + /** + * + * + *
+   * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements in
+   * 'extra_statements' above.
+   * Contains a protobuf-serialized
+   * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+   * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+   * run `protoc` with --include_imports and --descriptor_set_out. For example,
+   * to generate for moon/shot/app.proto, run
+   * """
+   * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+   *          --include_imports \
+   *          --descriptor_set_out=descriptors.data \
+   *          moon/shot/app.proto
+   * """
+   * For more details, see protobuffer [self
+   * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+   * 
+ * + * bytes proto_descriptors = 6 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The protoDescriptors. + */ + com.google.protobuf.ByteString getProtoDescriptors(); } diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/GetDatabaseDdlResponse.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/GetDatabaseDdlResponse.java index 39078a788f9..8a34b0f1df6 100644 --- a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/GetDatabaseDdlResponse.java +++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/GetDatabaseDdlResponse.java @@ -39,6 +39,7 @@ private GetDatabaseDdlResponse(com.google.protobuf.GeneratedMessageV3.Builder private GetDatabaseDdlResponse() { statements_ = com.google.protobuf.LazyStringArrayList.EMPTY; + protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; } @java.lang.Override @@ -132,6 +133,28 @@ public com.google.protobuf.ByteString getStatementsBytes(int index) { return statements_.getByteString(index); } + public static final int PROTO_DESCRIPTORS_FIELD_NUMBER = 2; + private com.google.protobuf.ByteString protoDescriptors_; + /** + * + * + *
+   * Proto descriptors stored in the database.
+   * Contains a protobuf-serialized
+   * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+   * For more details, see protobuffer [self
+   * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+   * 
+ * + * bytes proto_descriptors = 2; + * + * @return The protoDescriptors. + */ + @java.lang.Override + public com.google.protobuf.ByteString getProtoDescriptors() { + return protoDescriptors_; + } + private byte memoizedIsInitialized = -1; @java.lang.Override @@ -149,6 +172,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io for (int i = 0; i < statements_.size(); i++) { com.google.protobuf.GeneratedMessageV3.writeString(output, 1, statements_.getRaw(i)); } + if (!protoDescriptors_.isEmpty()) { + output.writeBytes(2, protoDescriptors_); + } getUnknownFields().writeTo(output); } @@ -166,6 +192,9 @@ public int getSerializedSize() { size += dataSize; size += 1 * getStatementsList().size(); } + if (!protoDescriptors_.isEmpty()) { + size += com.google.protobuf.CodedOutputStream.computeBytesSize(2, protoDescriptors_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -183,6 +212,7 @@ public boolean equals(final java.lang.Object obj) { (com.google.spanner.admin.database.v1.GetDatabaseDdlResponse) obj; if (!getStatementsList().equals(other.getStatementsList())) return false; + if (!getProtoDescriptors().equals(other.getProtoDescriptors())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -198,6 +228,8 @@ public int hashCode() { hash = (37 * hash) + STATEMENTS_FIELD_NUMBER; hash = (53 * hash) + getStatementsList().hashCode(); } + hash = (37 * hash) + PROTO_DESCRIPTORS_FIELD_NUMBER; + hash = (53 * hash) + getProtoDescriptors().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -339,6 +371,8 @@ public Builder clear() { super.clear(); statements_ = com.google.protobuf.LazyStringArrayList.EMPTY; bitField0_ = (bitField0_ & ~0x00000001); + protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; + return this; } @@ -372,6 +406,7 @@ public com.google.spanner.admin.database.v1.GetDatabaseDdlResponse buildPartial( bitField0_ = (bitField0_ & ~0x00000001); } result.statements_ = statements_; + result.protoDescriptors_ = protoDescriptors_; onBuilt(); return result; } @@ -432,6 +467,9 @@ public Builder mergeFrom(com.google.spanner.admin.database.v1.GetDatabaseDdlResp } onChanged(); } + if (other.getProtoDescriptors() != com.google.protobuf.ByteString.EMPTY) { + setProtoDescriptors(other.getProtoDescriptors()); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -465,6 +503,12 @@ public Builder mergeFrom( statements_.add(s); break; } // case 10 + case 18: + { + protoDescriptors_ = input.readBytes(); + + break; + } // case 18 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { @@ -661,6 +705,73 @@ public Builder addStatementsBytes(com.google.protobuf.ByteString value) { return this; } + private com.google.protobuf.ByteString protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; + /** + * + * + *
+     * Proto descriptors stored in the database.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * 
+ * + * bytes proto_descriptors = 2; + * + * @return The protoDescriptors. + */ + @java.lang.Override + public com.google.protobuf.ByteString getProtoDescriptors() { + return protoDescriptors_; + } + /** + * + * + *
+     * Proto descriptors stored in the database.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * 
+ * + * bytes proto_descriptors = 2; + * + * @param value The protoDescriptors to set. + * @return This builder for chaining. + */ + public Builder setProtoDescriptors(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + + protoDescriptors_ = value; + onChanged(); + return this; + } + /** + * + * + *
+     * Proto descriptors stored in the database.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * 
+ * + * bytes proto_descriptors = 2; + * + * @return This builder for chaining. + */ + public Builder clearProtoDescriptors() { + + protoDescriptors_ = getDefaultInstance().getProtoDescriptors(); + onChanged(); + return this; + } + @java.lang.Override public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { return super.setUnknownFields(unknownFields); diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/GetDatabaseDdlResponseOrBuilder.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/GetDatabaseDdlResponseOrBuilder.java index 28f7fb2cc5c..8f45b73c48c 100644 --- a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/GetDatabaseDdlResponseOrBuilder.java +++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/GetDatabaseDdlResponseOrBuilder.java @@ -77,4 +77,21 @@ public interface GetDatabaseDdlResponseOrBuilder * @return The bytes of the statements at the given index. */ com.google.protobuf.ByteString getStatementsBytes(int index); + + /** + * + * + *
+   * Proto descriptors stored in the database.
+   * Contains a protobuf-serialized
+   * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+   * For more details, see protobuffer [self
+   * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+   * 
+ * + * bytes proto_descriptors = 2; + * + * @return The protoDescriptors. + */ + com.google.protobuf.ByteString getProtoDescriptors(); } diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SpannerDatabaseAdminProto.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SpannerDatabaseAdminProto.java index 9a4c1888ef2..8a0a0250c2f 100644 --- a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SpannerDatabaseAdminProto.java +++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SpannerDatabaseAdminProto.java @@ -161,7 +161,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\030\003 \001(\005\022\022\n\npage_token\030\004 \001(\t\"o\n\025ListDataba" + "sesResponse\022=\n\tdatabases\030\001 \003(\0132*.google." + "spanner.admin.database.v1.Database\022\027\n\017ne" - + "xt_page_token\030\002 \001(\t\"\264\002\n\025CreateDatabaseRe" + + "xt_page_token\030\002 \001(\t\"\324\002\n\025CreateDatabaseRe" + "quest\0227\n\006parent\030\001 \001(\tB\'\340A\002\372A!\n\037spanner.g" + "oogleapis.com/Instance\022\035\n\020create_stateme" + "nt\030\002 \001(\tB\003\340A\002\022\035\n\020extra_statements\030\003 \003(\tB" @@ -169,198 +169,200 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + ".spanner.admin.database.v1.EncryptionCon" + "figB\003\340A\001\022P\n\020database_dialect\030\005 \001(\01621.goo" + "gle.spanner.admin.database.v1.DatabaseDi" - + "alectB\003\340A\001\"P\n\026CreateDatabaseMetadata\0226\n\010" - + "database\030\001 \001(\tB$\372A!\n\037spanner.googleapis." - + "com/Database\"K\n\022GetDatabaseRequest\0225\n\004na" - + "me\030\001 \001(\tB\'\340A\002\372A!\n\037spanner.googleapis.com" - + "/Database\"\204\001\n\030UpdateDatabaseDdlRequest\0229" - + "\n\010database\030\001 \001(\tB\'\340A\002\372A!\n\037spanner.google" - + "apis.com/Database\022\027\n\nstatements\030\002 \003(\tB\003\340" - + "A\002\022\024\n\014operation_id\030\003 \001(\t\"\375\001\n\031UpdateDatab" - + "aseDdlMetadata\0226\n\010database\030\001 \001(\tB$\372A!\n\037s" - + "panner.googleapis.com/Database\022\022\n\nstatem" - + "ents\030\002 \003(\t\0225\n\021commit_timestamps\030\003 \003(\0132\032." - + "google.protobuf.Timestamp\022\026\n\tthrottled\030\004" - + " \001(\010B\003\340A\003\022E\n\010progress\030\005 \003(\01323.google.spa" - + "nner.admin.database.v1.OperationProgress" - + "\"P\n\023DropDatabaseRequest\0229\n\010database\030\001 \001(" - + "\tB\'\340A\002\372A!\n\037spanner.googleapis.com/Databa" - + "se\"R\n\025GetDatabaseDdlRequest\0229\n\010database\030" - + "\001 \001(\tB\'\340A\002\372A!\n\037spanner.googleapis.com/Da" - + "tabase\",\n\026GetDatabaseDdlResponse\022\022\n\nstat" - + "ements\030\001 \003(\t\"\217\001\n\035ListDatabaseOperationsR" - + "equest\0227\n\006parent\030\001 \001(\tB\'\340A\002\372A!\n\037spanner." - + "googleapis.com/Instance\022\016\n\006filter\030\002 \001(\t\022" - + "\021\n\tpage_size\030\003 \001(\005\022\022\n\npage_token\030\004 \001(\t\"l" - + "\n\036ListDatabaseOperationsResponse\0221\n\noper" - + "ations\030\001 \003(\0132\035.google.longrunning.Operat" - + "ion\022\027\n\017next_page_token\030\002 \001(\t\"\216\002\n\026Restore" - + "DatabaseRequest\0227\n\006parent\030\001 \001(\tB\'\340A\002\372A!\n" - + "\037spanner.googleapis.com/Instance\022\030\n\013data" - + "base_id\030\002 \001(\tB\003\340A\002\0224\n\006backup\030\003 \001(\tB\"\372A\037\n" - + "\035spanner.googleapis.com/BackupH\000\022a\n\021encr" - + "yption_config\030\004 \001(\0132A.google.spanner.adm" - + "in.database.v1.RestoreDatabaseEncryption" - + "ConfigB\003\340A\001B\010\n\006source\"\363\002\n\037RestoreDatabas" - + "eEncryptionConfig\022n\n\017encryption_type\030\001 \001" - + "(\0162P.google.spanner.admin.database.v1.Re" - + "storeDatabaseEncryptionConfig.Encryption" - + "TypeB\003\340A\002\022?\n\014kms_key_name\030\002 \001(\tB)\340A\001\372A#\n" - + "!cloudkms.googleapis.com/CryptoKey\"\236\001\n\016E" - + "ncryptionType\022\037\n\033ENCRYPTION_TYPE_UNSPECI" - + "FIED\020\000\022+\n\'USE_CONFIG_DEFAULT_OR_BACKUP_E" - + "NCRYPTION\020\001\022\035\n\031GOOGLE_DEFAULT_ENCRYPTION" - + "\020\002\022\037\n\033CUSTOMER_MANAGED_ENCRYPTION\020\003\"\215\003\n\027" - + "RestoreDatabaseMetadata\0222\n\004name\030\001 \001(\tB$\372" - + "A!\n\037spanner.googleapis.com/Database\022H\n\013s" - + "ource_type\030\002 \001(\01623.google.spanner.admin." - + "database.v1.RestoreSourceType\022C\n\013backup_" - + "info\030\003 \001(\0132,.google.spanner.admin.databa" - + "se.v1.BackupInfoH\000\022E\n\010progress\030\004 \001(\01323.g" - + "oogle.spanner.admin.database.v1.Operatio" - + "nProgress\022/\n\013cancel_time\030\005 \001(\0132\032.google." - + "protobuf.Timestamp\022(\n optimize_database_" - + "operation_name\030\006 \001(\tB\r\n\013source_info\"\235\001\n " - + "OptimizeRestoredDatabaseMetadata\0222\n\004name" + + "alectB\003\340A\001\022\036\n\021proto_descriptors\030\006 \001(\014B\003\340" + + "A\001\"P\n\026CreateDatabaseMetadata\0226\n\010database" + "\030\001 \001(\tB$\372A!\n\037spanner.googleapis.com/Data" - + "base\022E\n\010progress\030\002 \001(\01323.google.spanner." - + "admin.database.v1.OperationProgress\"\236\001\n\014" - + "DatabaseRole\022\021\n\004name\030\001 \001(\tB\003\340A\002:{\352Ax\n#sp" - + "anner.googleapis.com/DatabaseRole\022Qproje" - + "cts/{project}/instances/{instance}/datab" - + "ases/{database}/databaseRoles/{role}\"z\n\030" - + "ListDatabaseRolesRequest\0227\n\006parent\030\001 \001(\t" + + "base\"K\n\022GetDatabaseRequest\0225\n\004name\030\001 \001(\t" + "B\'\340A\002\372A!\n\037spanner.googleapis.com/Databas" - + "e\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t" - + "\"|\n\031ListDatabaseRolesResponse\022F\n\016databas" - + "e_roles\030\001 \003(\0132..google.spanner.admin.dat" - + "abase.v1.DatabaseRole\022\027\n\017next_page_token" - + "\030\002 \001(\t*5\n\021RestoreSourceType\022\024\n\020TYPE_UNSP" - + "ECIFIED\020\000\022\n\n\006BACKUP\020\0012\374#\n\rDatabaseAdmin\022" - + "\300\001\n\rListDatabases\0226.google.spanner.admin" - + ".database.v1.ListDatabasesRequest\0327.goog" - + "le.spanner.admin.database.v1.ListDatabas" - + "esResponse\">\202\323\344\223\002/\022-/v1/{parent=projects" - + "/*/instances/*}/databases\332A\006parent\022\244\002\n\016C" - + "reateDatabase\0227.google.spanner.admin.dat" - + "abase.v1.CreateDatabaseRequest\032\035.google." - + "longrunning.Operation\"\271\001\202\323\344\223\0022\"-/v1/{par" - + "ent=projects/*/instances/*}/databases:\001*" - + "\332A\027parent,create_statement\312Ad\n)google.sp" - + "anner.admin.database.v1.Database\0227google" - + ".spanner.admin.database.v1.CreateDatabas" - + "eMetadata\022\255\001\n\013GetDatabase\0224.google.spann" - + "er.admin.database.v1.GetDatabaseRequest\032" - + "*.google.spanner.admin.database.v1.Datab" - + "ase\"<\202\323\344\223\002/\022-/v1/{name=projects/*/instan" - + "ces/*/databases/*}\332A\004name\022\235\002\n\021UpdateData" - + "baseDdl\022:.google.spanner.admin.database." - + "v1.UpdateDatabaseDdlRequest\032\035.google.lon" - + "grunning.Operation\"\254\001\202\323\344\223\002:25/v1/{databa" - + "se=projects/*/instances/*/databases/*}/d" - + "dl:\001*\332A\023database,statements\312AS\n\025google.p" - + "rotobuf.Empty\022:google.spanner.admin.data" - + "base.v1.UpdateDatabaseDdlMetadata\022\243\001\n\014Dr" - + "opDatabase\0225.google.spanner.admin.databa" - + "se.v1.DropDatabaseRequest\032\026.google.proto" - + "buf.Empty\"D\202\323\344\223\0023*1/v1/{database=project" - + "s/*/instances/*/databases/*}\332A\010database\022" - + "\315\001\n\016GetDatabaseDdl\0227.google.spanner.admi" - + "n.database.v1.GetDatabaseDdlRequest\0328.go" - + "ogle.spanner.admin.database.v1.GetDataba" - + "seDdlResponse\"H\202\323\344\223\0027\0225/v1/{database=pro" - + "jects/*/instances/*/databases/*}/ddl\332A\010d" - + "atabase\022\353\001\n\014SetIamPolicy\022\".google.iam.v1" - + ".SetIamPolicyRequest\032\025.google.iam.v1.Pol" - + "icy\"\237\001\202\323\344\223\002\206\001\">/v1/{resource=projects/*/" - + "instances/*/databases/*}:setIamPolicy:\001*" - + "ZA\"/v1/{resource=projects/*/in" - + "stances/*/databases/*}:getIamPolicy:\001*ZA" - + "\".google.sp" - + "anner.admin.database.v1.ListBackupOperat" - + "ionsResponse\"E\202\323\344\223\0026\0224/v1/{parent=projec" - + "ts/*/instances/*}/backupOperations\332A\006par" - + "ent\022\334\001\n\021ListDatabaseRoles\022:.google.spann" - + "er.admin.database.v1.ListDatabaseRolesRe" - + "quest\032;.google.spanner.admin.database.v1" - + ".ListDatabaseRolesResponse\"N\202\323\344\223\002?\022=/v1/" - + "{parent=projects/*/instances/*/databases" - + "/*}/databaseRoles\332A\006parent\032x\312A\026spanner.g" - + "oogleapis.com\322A\\https://www.googleapis.c" - + "om/auth/cloud-platform,https://www.googl" - + "eapis.com/auth/spanner.adminB\332\002\n$com.goo" - + "gle.spanner.admin.database.v1B\031SpannerDa" - + "tabaseAdminProtoP\001ZHgoogle.golang.org/ge" - + "nproto/googleapis/spanner/admin/database" - + "/v1;database\252\002&Google.Cloud.Spanner.Admi" - + "n.Database.V1\312\002&Google\\Cloud\\Spanner\\Adm" - + "in\\Database\\V1\352\002+Google::Cloud::Spanner:" - + ":Admin::Database::V1\352AJ\n\037spanner.googlea" - + "pis.com/Instance\022\'projects/{project}/ins" - + "tances/{instance}b\006proto3" + + "e\"\244\001\n\030UpdateDatabaseDdlRequest\0229\n\010databa" + + "se\030\001 \001(\tB\'\340A\002\372A!\n\037spanner.googleapis.com" + + "/Database\022\027\n\nstatements\030\002 \003(\tB\003\340A\002\022\024\n\014op" + + "eration_id\030\003 \001(\t\022\036\n\021proto_descriptors\030\004 " + + "\001(\014B\003\340A\001\"\375\001\n\031UpdateDatabaseDdlMetadata\0226" + + "\n\010database\030\001 \001(\tB$\372A!\n\037spanner.googleapi" + + "s.com/Database\022\022\n\nstatements\030\002 \003(\t\0225\n\021co" + + "mmit_timestamps\030\003 \003(\0132\032.google.protobuf." + + "Timestamp\022\026\n\tthrottled\030\004 \001(\010B\003\340A\003\022E\n\010pro" + + "gress\030\005 \003(\01323.google.spanner.admin.datab" + + "ase.v1.OperationProgress\"P\n\023DropDatabase" + + "Request\0229\n\010database\030\001 \001(\tB\'\340A\002\372A!\n\037spann" + + "er.googleapis.com/Database\"R\n\025GetDatabas" + + "eDdlRequest\0229\n\010database\030\001 \001(\tB\'\340A\002\372A!\n\037s" + + "panner.googleapis.com/Database\"G\n\026GetDat" + + "abaseDdlResponse\022\022\n\nstatements\030\001 \003(\t\022\031\n\021" + + "proto_descriptors\030\002 \001(\014\"\217\001\n\035ListDatabase" + + "OperationsRequest\0227\n\006parent\030\001 \001(\tB\'\340A\002\372A" + + "!\n\037spanner.googleapis.com/Instance\022\016\n\006fi" + + "lter\030\002 \001(\t\022\021\n\tpage_size\030\003 \001(\005\022\022\n\npage_to" + + "ken\030\004 \001(\t\"l\n\036ListDatabaseOperationsRespo" + + "nse\0221\n\noperations\030\001 \003(\0132\035.google.longrun" + + "ning.Operation\022\027\n\017next_page_token\030\002 \001(\t\"" + + "\216\002\n\026RestoreDatabaseRequest\0227\n\006parent\030\001 \001" + + "(\tB\'\340A\002\372A!\n\037spanner.googleapis.com/Insta" + + "nce\022\030\n\013database_id\030\002 \001(\tB\003\340A\002\0224\n\006backup\030" + + "\003 \001(\tB\"\372A\037\n\035spanner.googleapis.com/Backu" + + "pH\000\022a\n\021encryption_config\030\004 \001(\0132A.google." + + "spanner.admin.database.v1.RestoreDatabas" + + "eEncryptionConfigB\003\340A\001B\010\n\006source\"\363\002\n\037Res" + + "toreDatabaseEncryptionConfig\022n\n\017encrypti" + + "on_type\030\001 \001(\0162P.google.spanner.admin.dat" + + "abase.v1.RestoreDatabaseEncryptionConfig" + + ".EncryptionTypeB\003\340A\002\022?\n\014kms_key_name\030\002 \001" + + "(\tB)\340A\001\372A#\n!cloudkms.googleapis.com/Cryp" + + "toKey\"\236\001\n\016EncryptionType\022\037\n\033ENCRYPTION_T" + + "YPE_UNSPECIFIED\020\000\022+\n\'USE_CONFIG_DEFAULT_" + + "OR_BACKUP_ENCRYPTION\020\001\022\035\n\031GOOGLE_DEFAULT" + + "_ENCRYPTION\020\002\022\037\n\033CUSTOMER_MANAGED_ENCRYP" + + "TION\020\003\"\215\003\n\027RestoreDatabaseMetadata\0222\n\004na" + + "me\030\001 \001(\tB$\372A!\n\037spanner.googleapis.com/Da" + + "tabase\022H\n\013source_type\030\002 \001(\01623.google.spa" + + "nner.admin.database.v1.RestoreSourceType" + + "\022C\n\013backup_info\030\003 \001(\0132,.google.spanner.a" + + "dmin.database.v1.BackupInfoH\000\022E\n\010progres" + + "s\030\004 \001(\01323.google.spanner.admin.database." + + "v1.OperationProgress\022/\n\013cancel_time\030\005 \001(" + + "\0132\032.google.protobuf.Timestamp\022(\n optimiz" + + "e_database_operation_name\030\006 \001(\tB\r\n\013sourc" + + "e_info\"\235\001\n OptimizeRestoredDatabaseMetad" + + "ata\0222\n\004name\030\001 \001(\tB$\372A!\n\037spanner.googleap" + + "is.com/Database\022E\n\010progress\030\002 \001(\01323.goog" + + "le.spanner.admin.database.v1.OperationPr" + + "ogress\"\236\001\n\014DatabaseRole\022\021\n\004name\030\001 \001(\tB\003\340" + + "A\002:{\352Ax\n#spanner.googleapis.com/Database" + + "Role\022Qprojects/{project}/instances/{inst" + + "ance}/databases/{database}/databaseRoles" + + "/{role}\"z\n\030ListDatabaseRolesRequest\0227\n\006p" + + "arent\030\001 \001(\tB\'\340A\002\372A!\n\037spanner.googleapis." + + "com/Database\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npage_" + + "token\030\003 \001(\t\"|\n\031ListDatabaseRolesResponse" + + "\022F\n\016database_roles\030\001 \003(\0132..google.spanne" + + "r.admin.database.v1.DatabaseRole\022\027\n\017next" + + "_page_token\030\002 \001(\t*5\n\021RestoreSourceType\022\024" + + "\n\020TYPE_UNSPECIFIED\020\000\022\n\n\006BACKUP\020\0012\374#\n\rDat" + + "abaseAdmin\022\300\001\n\rListDatabases\0226.google.sp" + + "anner.admin.database.v1.ListDatabasesReq" + + "uest\0327.google.spanner.admin.database.v1." + + "ListDatabasesResponse\">\202\323\344\223\002/\022-/v1/{pare" + + "nt=projects/*/instances/*}/databases\332A\006p" + + "arent\022\244\002\n\016CreateDatabase\0227.google.spanne" + + "r.admin.database.v1.CreateDatabaseReques" + + "t\032\035.google.longrunning.Operation\"\271\001\202\323\344\223\002" + + "2\"-/v1/{parent=projects/*/instances/*}/d" + + "atabases:\001*\332A\027parent,create_statement\312Ad" + + "\n)google.spanner.admin.database.v1.Datab" + + "ase\0227google.spanner.admin.database.v1.Cr" + + "eateDatabaseMetadata\022\255\001\n\013GetDatabase\0224.g" + + "oogle.spanner.admin.database.v1.GetDatab" + + "aseRequest\032*.google.spanner.admin.databa" + + "se.v1.Database\"<\202\323\344\223\002/\022-/v1/{name=projec" + + "ts/*/instances/*/databases/*}\332A\004name\022\235\002\n" + + "\021UpdateDatabaseDdl\022:.google.spanner.admi" + + "n.database.v1.UpdateDatabaseDdlRequest\032\035" + + ".google.longrunning.Operation\"\254\001\202\323\344\223\002:25" + + "/v1/{database=projects/*/instances/*/dat" + + "abases/*}/ddl:\001*\332A\023database,statements\312A" + + "S\n\025google.protobuf.Empty\022:google.spanner" + + ".admin.database.v1.UpdateDatabaseDdlMeta" + + "data\022\243\001\n\014DropDatabase\0225.google.spanner.a" + + "dmin.database.v1.DropDatabaseRequest\032\026.g" + + "oogle.protobuf.Empty\"D\202\323\344\223\0023*1/v1/{datab" + + "ase=projects/*/instances/*/databases/*}\332" + + "A\010database\022\315\001\n\016GetDatabaseDdl\0227.google.s" + + "panner.admin.database.v1.GetDatabaseDdlR" + + "equest\0328.google.spanner.admin.database.v" + + "1.GetDatabaseDdlResponse\"H\202\323\344\223\0027\0225/v1/{d" + + "atabase=projects/*/instances/*/databases" + + "/*}/ddl\332A\010database\022\353\001\n\014SetIamPolicy\022\".go" + + "ogle.iam.v1.SetIamPolicyRequest\032\025.google" + + ".iam.v1.Policy\"\237\001\202\323\344\223\002\206\001\">/v1/{resource=" + + "projects/*/instances/*/databases/*}:setI" + + "amPolicy:\001*ZA\"/v1/{resource=pr" + + "ojects/*/instances/*/databases/*}:getIam" + + "Policy:\001*ZA\".google.spanner.admin.database.v1.ListB" + + "ackupOperationsResponse\"E\202\323\344\223\0026\0224/v1/{pa" + + "rent=projects/*/instances/*}/backupOpera" + + "tions\332A\006parent\022\334\001\n\021ListDatabaseRoles\022:.g" + + "oogle.spanner.admin.database.v1.ListData" + + "baseRolesRequest\032;.google.spanner.admin." + + "database.v1.ListDatabaseRolesResponse\"N\202" + + "\323\344\223\002?\022=/v1/{parent=projects/*/instances/" + + "*/databases/*}/databaseRoles\332A\006parent\032x\312" + + "A\026spanner.googleapis.com\322A\\https://www.g" + + "oogleapis.com/auth/cloud-platform,https:" + + "//www.googleapis.com/auth/spanner.adminB" + + "\332\002\n$com.google.spanner.admin.database.v1" + + "B\031SpannerDatabaseAdminProtoP\001ZHgoogle.go" + + "lang.org/genproto/googleapis/spanner/adm" + + "in/database/v1;database\252\002&Google.Cloud.S" + + "panner.Admin.Database.V1\312\002&Google\\Cloud\\" + + "Spanner\\Admin\\Database\\V1\352\002+Google::Clou" + + "d::Spanner::Admin::Database::V1\352AJ\n\037span" + + "ner.googleapis.com/Instance\022\'projects/{p" + + "roject}/instances/{instance}b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom( @@ -425,7 +427,12 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_spanner_admin_database_v1_CreateDatabaseRequest_descriptor, new java.lang.String[] { - "Parent", "CreateStatement", "ExtraStatements", "EncryptionConfig", "DatabaseDialect", + "Parent", + "CreateStatement", + "ExtraStatements", + "EncryptionConfig", + "DatabaseDialect", + "ProtoDescriptors", }); internal_static_google_spanner_admin_database_v1_CreateDatabaseMetadata_descriptor = getDescriptor().getMessageTypes().get(5); @@ -449,7 +456,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_spanner_admin_database_v1_UpdateDatabaseDdlRequest_descriptor, new java.lang.String[] { - "Database", "Statements", "OperationId", + "Database", "Statements", "OperationId", "ProtoDescriptors", }); internal_static_google_spanner_admin_database_v1_UpdateDatabaseDdlMetadata_descriptor = getDescriptor().getMessageTypes().get(8); @@ -481,7 +488,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_spanner_admin_database_v1_GetDatabaseDdlResponse_descriptor, new java.lang.String[] { - "Statements", + "Statements", "ProtoDescriptors", }); internal_static_google_spanner_admin_database_v1_ListDatabaseOperationsRequest_descriptor = getDescriptor().getMessageTypes().get(12); diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/UpdateDatabaseDdlRequest.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/UpdateDatabaseDdlRequest.java index 3911178f357..b698ca808f4 100644 --- a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/UpdateDatabaseDdlRequest.java +++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/UpdateDatabaseDdlRequest.java @@ -55,6 +55,7 @@ private UpdateDatabaseDdlRequest() { database_ = ""; statements_ = com.google.protobuf.LazyStringArrayList.EMPTY; operationId_ = ""; + protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; } @java.lang.Override @@ -278,6 +279,43 @@ public com.google.protobuf.ByteString getOperationIdBytes() { } } + public static final int PROTO_DESCRIPTORS_FIELD_NUMBER = 4; + private com.google.protobuf.ByteString protoDescriptors_; + /** + * + * + *
+   * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements.
+   * Contains a protobuf-serialized
+   * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+   * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+   * run `protoc` with --include_imports and --descriptor_set_out. For example,
+   * to generate for moon/shot/app.proto, run
+   * """
+   * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+   *          --include_imports \
+   *          --descriptor_set_out=descriptors.data \
+   *          moon/shot/app.proto
+   * """
+   * For more details, see protobuffer [self
+   * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+   * (--
+   * TODO(b/236424835) remove visibility check before launch.
+   * --)
+   * (-- api-linter: core::0134::request-unknown-fields=disabled
+   *     aip.dev/not-precedent: This Update*Request provides an alter action
+   *     rather than the usual entity field updating. --)
+   * 
+ * + * bytes proto_descriptors = 4 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The protoDescriptors. + */ + @java.lang.Override + public com.google.protobuf.ByteString getProtoDescriptors() { + return protoDescriptors_; + } + private byte memoizedIsInitialized = -1; @java.lang.Override @@ -301,6 +339,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(operationId_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 3, operationId_); } + if (!protoDescriptors_.isEmpty()) { + output.writeBytes(4, protoDescriptors_); + } getUnknownFields().writeTo(output); } @@ -324,6 +365,9 @@ public int getSerializedSize() { if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(operationId_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, operationId_); } + if (!protoDescriptors_.isEmpty()) { + size += com.google.protobuf.CodedOutputStream.computeBytesSize(4, protoDescriptors_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -343,6 +387,7 @@ public boolean equals(final java.lang.Object obj) { if (!getDatabase().equals(other.getDatabase())) return false; if (!getStatementsList().equals(other.getStatementsList())) return false; if (!getOperationId().equals(other.getOperationId())) return false; + if (!getProtoDescriptors().equals(other.getProtoDescriptors())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -362,6 +407,8 @@ public int hashCode() { } hash = (37 * hash) + OPERATION_ID_FIELD_NUMBER; hash = (53 * hash) + getOperationId().hashCode(); + hash = (37 * hash) + PROTO_DESCRIPTORS_FIELD_NUMBER; + hash = (53 * hash) + getProtoDescriptors().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -521,6 +568,8 @@ public Builder clear() { bitField0_ = (bitField0_ & ~0x00000001); operationId_ = ""; + protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; + return this; } @@ -557,6 +606,7 @@ public com.google.spanner.admin.database.v1.UpdateDatabaseDdlRequest buildPartia } result.statements_ = statements_; result.operationId_ = operationId_; + result.protoDescriptors_ = protoDescriptors_; onBuilt(); return result; } @@ -626,6 +676,9 @@ public Builder mergeFrom(com.google.spanner.admin.database.v1.UpdateDatabaseDdlR operationId_ = other.operationId_; onChanged(); } + if (other.getProtoDescriptors() != com.google.protobuf.ByteString.EMPTY) { + setProtoDescriptors(other.getProtoDescriptors()); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -671,6 +724,12 @@ public Builder mergeFrom( break; } // case 26 + case 34: + { + protoDescriptors_ = input.readBytes(); + + break; + } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { @@ -1160,6 +1219,118 @@ public Builder setOperationIdBytes(com.google.protobuf.ByteString value) { return this; } + private com.google.protobuf.ByteString protoDescriptors_ = com.google.protobuf.ByteString.EMPTY; + /** + * + * + *
+     * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+     * run `protoc` with --include_imports and --descriptor_set_out. For example,
+     * to generate for moon/shot/app.proto, run
+     * """
+     * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+     *          --include_imports \
+     *          --descriptor_set_out=descriptors.data \
+     *          moon/shot/app.proto
+     * """
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * (--
+     * TODO(b/236424835) remove visibility check before launch.
+     * --)
+     * (-- api-linter: core::0134::request-unknown-fields=disabled
+     *     aip.dev/not-precedent: This Update*Request provides an alter action
+     *     rather than the usual entity field updating. --)
+     * 
+ * + * bytes proto_descriptors = 4 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The protoDescriptors. + */ + @java.lang.Override + public com.google.protobuf.ByteString getProtoDescriptors() { + return protoDescriptors_; + } + /** + * + * + *
+     * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+     * run `protoc` with --include_imports and --descriptor_set_out. For example,
+     * to generate for moon/shot/app.proto, run
+     * """
+     * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+     *          --include_imports \
+     *          --descriptor_set_out=descriptors.data \
+     *          moon/shot/app.proto
+     * """
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * (--
+     * TODO(b/236424835) remove visibility check before launch.
+     * --)
+     * (-- api-linter: core::0134::request-unknown-fields=disabled
+     *     aip.dev/not-precedent: This Update*Request provides an alter action
+     *     rather than the usual entity field updating. --)
+     * 
+ * + * bytes proto_descriptors = 4 [(.google.api.field_behavior) = OPTIONAL]; + * + * @param value The protoDescriptors to set. + * @return This builder for chaining. + */ + public Builder setProtoDescriptors(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + + protoDescriptors_ = value; + onChanged(); + return this; + } + /** + * + * + *
+     * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements.
+     * Contains a protobuf-serialized
+     * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+     * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+     * run `protoc` with --include_imports and --descriptor_set_out. For example,
+     * to generate for moon/shot/app.proto, run
+     * """
+     * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+     *          --include_imports \
+     *          --descriptor_set_out=descriptors.data \
+     *          moon/shot/app.proto
+     * """
+     * For more details, see protobuffer [self
+     * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+     * (--
+     * TODO(b/236424835) remove visibility check before launch.
+     * --)
+     * (-- api-linter: core::0134::request-unknown-fields=disabled
+     *     aip.dev/not-precedent: This Update*Request provides an alter action
+     *     rather than the usual entity field updating. --)
+     * 
+ * + * bytes proto_descriptors = 4 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return This builder for chaining. + */ + public Builder clearProtoDescriptors() { + + protoDescriptors_ = getDefaultInstance().getProtoDescriptors(); + onChanged(); + return this; + } + @java.lang.Override public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { return super.setUnknownFields(unknownFields); diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/UpdateDatabaseDdlRequestOrBuilder.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/UpdateDatabaseDdlRequestOrBuilder.java index cad7c3a28a2..ba445dc1a18 100644 --- a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/UpdateDatabaseDdlRequestOrBuilder.java +++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/UpdateDatabaseDdlRequestOrBuilder.java @@ -159,4 +159,36 @@ public interface UpdateDatabaseDdlRequestOrBuilder * @return The bytes for operationId. */ com.google.protobuf.ByteString getOperationIdBytes(); + + /** + * + * + *
+   * Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements.
+   * Contains a protobuf-serialized
+   * [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+   * To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+   * run `protoc` with --include_imports and --descriptor_set_out. For example,
+   * to generate for moon/shot/app.proto, run
+   * """
+   * $protoc  --proto_path=/app_path --proto_path=/lib_path \
+   *          --include_imports \
+   *          --descriptor_set_out=descriptors.data \
+   *          moon/shot/app.proto
+   * """
+   * For more details, see protobuffer [self
+   * description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+   * (--
+   * TODO(b/236424835) remove visibility check before launch.
+   * --)
+   * (-- api-linter: core::0134::request-unknown-fields=disabled
+   *     aip.dev/not-precedent: This Update*Request provides an alter action
+   *     rather than the usual entity field updating. --)
+   * 
+ * + * bytes proto_descriptors = 4 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The protoDescriptors. + */ + com.google.protobuf.ByteString getProtoDescriptors(); } diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/proto/google/spanner/admin/database/v1/spanner_database_admin.proto b/proto-google-cloud-spanner-admin-database-v1/src/main/proto/google/spanner/admin/database/v1/spanner_database_admin.proto index 91489ae4b45..f27617c4f09 100644 --- a/proto-google-cloud-spanner-admin-database-v1/src/main/proto/google/spanner/admin/database/v1/spanner_database_admin.proto +++ b/proto-google-cloud-spanner-admin-database-v1/src/main/proto/google/spanner/admin/database/v1/spanner_database_admin.proto @@ -514,6 +514,23 @@ message CreateDatabaseRequest { // Optional. The dialect of the Cloud Spanner Database. DatabaseDialect database_dialect = 5 [(google.api.field_behavior) = OPTIONAL]; + + // Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements in + // 'extra_statements' above. + // Contains a protobuf-serialized + // [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto). + // To generate it, [install](https://grpc.io/docs/protoc-installation/) and + // run `protoc` with --include_imports and --descriptor_set_out. For example, + // to generate for moon/shot/app.proto, run + // """ + // $protoc --proto_path=/app_path --proto_path=/lib_path \ + // --include_imports \ + // --descriptor_set_out=descriptors.data \ + // moon/shot/app.proto + // """ + // For more details, see protobuffer [self + // description](https://developers.google.com/protocol-buffers/docs/techniques#self-description). + bytes proto_descriptors = 6 [(google.api.field_behavior) = OPTIONAL]; } // Metadata type for the operation returned by @@ -585,6 +602,28 @@ message UpdateDatabaseDdlRequest { // [UpdateDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabaseDdl] returns // `ALREADY_EXISTS`. string operation_id = 3; + + // Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements. + // Contains a protobuf-serialized + // [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto). + // To generate it, [install](https://grpc.io/docs/protoc-installation/) and + // run `protoc` with --include_imports and --descriptor_set_out. For example, + // to generate for moon/shot/app.proto, run + // """ + // $protoc --proto_path=/app_path --proto_path=/lib_path \ + // --include_imports \ + // --descriptor_set_out=descriptors.data \ + // moon/shot/app.proto + // """ + // For more details, see protobuffer [self + // description](https://developers.google.com/protocol-buffers/docs/techniques#self-description). + // (-- + // TODO(b/236424835) remove visibility check before launch. + // --) + // (-- api-linter: core::0134::request-unknown-fields=disabled + // aip.dev/not-precedent: This Update*Request provides an alter action + // rather than the usual entity field updating. --) + bytes proto_descriptors = 4 [(google.api.field_behavior) = OPTIONAL]; } // Metadata type for the operation returned by @@ -649,6 +688,13 @@ message GetDatabaseDdlResponse { // A list of formatted DDL statements defining the schema of the database // specified in the request. repeated string statements = 1; + + // Proto descriptors stored in the database. + // Contains a protobuf-serialized + // [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto). + // For more details, see protobuffer [self + // description](https://developers.google.com/protocol-buffers/docs/techniques#self-description). + bytes proto_descriptors = 2; } // The request for