From ecd17031d1a3ffd710e258e2a915660f3fec4e7e Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Mon, 22 Apr 2019 08:14:13 -0700 Subject: [PATCH 01/13] initial model --- .../google-cloud-bigquery/pom.xml | 1 + .../java/com/google/cloud/bigquery/Model.java | 33 +++ .../com/google/cloud/bigquery/ModelId.java | 102 ++++++++ .../com/google/cloud/bigquery/ModelInfo.java | 237 ++++++++++++++++++ 4 files changed, 373 insertions(+) create mode 100644 google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java create mode 100644 google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java create mode 100644 google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java diff --git a/google-cloud-clients/google-cloud-bigquery/pom.xml b/google-cloud-clients/google-cloud-bigquery/pom.xml index 453af256ac51..13bf453979d9 100644 --- a/google-cloud-clients/google-cloud-bigquery/pom.xml +++ b/google-cloud-clients/google-cloud-bigquery/pom.xml @@ -39,6 +39,7 @@ com.google.apis google-api-services-bigquery + v2-rev431-1.24.1 compile diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java new file mode 100644 index 000000000000..9ccc27d58d21 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java @@ -0,0 +1,33 @@ +package com.google.cloud.bigquery; + + +/** + * A Google BigQuery ML Model. + * + *

Objects of this class are immutable. Operations that modify the table like {@link #update} + * return a new object. To get a {@code Model} object with the most recent information use {@link + * #reload}. + * + */ +public class Model extends ModelInfo { + + private final BigQUeryOptions options; + private transient BigQuery bigquery; + + public static class Builder extends ModelInfo.Builder { + + private final BigQUery bigquery; + private final ModelInfo.BuilderImpl infoBuilder; + + Builder(BigQuery bigquery, ModelId modelId, ModelDefinition definition) { + this.bigquery = bigquery; + this.infoBuilder = new ModelInfo.BuilderImpl(); + this.infoBuilder.setModelId(modelId).setDefinition(definition); + } + } + + + static Model fromPb(BigQuery bigquery, com.google.api.services.bigquery.model.Model modelPb) { + return new Table(bigquery, new ModelInfo.BuilderImpl(modelPb)); + } +} diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java new file mode 100644 index 000000000000..2d90f1c41f48 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java @@ -0,0 +1,102 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +package com.google.cloud.bigquery; + +import java.io.Serializable; +import java.util.Objects; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.api.services.bigquery.model.ModelReference; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.base.Function; + +public final class ModelId implements Serializable { + + static final Function FROM_PB_FUNCTION = + new Function() { + @Override + public ModelId apply(ModelReference pb) { + return ModelId.fromPb(pb); + } + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public ModelReference apply(ModelId modelId) { + return modelId.toPb(); + } + }; + + private final String project; + private final String dataset; + private final String model; + + /** Return corresponding project ID for this model. **/ + public String getProject() { return project; } + + /** Return corresponding dataset ID for this model. **/ + public String getDataset() { return dataset; } + + /** Return corresponding model ID for this model. **/ + public String getModel() { return model; } + + private ModelId(String project, String dataset, String model) { + this.project = project; + this.dataset = dataset; + this.model = model; + } + + /** Creates a model identity given project, dataset, and model identifiers. **/ + public static ModelId of(String project, String dataset, String model) { + return new ModelId(checkNotNull(project), checkNotNull(dataset), checkNotNull(model)); + } + + /** Creates a model identity given data and table identifiers. **/ + public static ModelId of(String dataset, String model) { + return new ModelId(null, checkNotNull(dataset), checkNotNull(model)); + } + + @Override public boolean equals(Object obj) { + return obj == this || obj instanceof ModelId && Objects.equals(toPb(), ((ModelId) obj).toPb()); + } + + @Override + public int hashCode() { + return Objects.hash(project, dataset, model); + } + + @Override + public String toString() { + return toPb().toString(); + } + + ModelId setProjectId(String projectId) { + Preconditions.checkArgument( + !Strings.isNullOrEmpty(projectId), "Provided projectId is null or empty"); + return ModelId.of(projectId, getDataset(), getModel()); + } + + ModelReference toPb() { return new ModelReference().setProjectId(project).setDatasetId(dataset).setModelId(model); } + + static ModelId fromPb(ModelReference modelRef) { + return new ModelId(modelRef.getProjectId(), modelRef.getDatasetId(), modelRef.getModelId()); + } +} diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java new file mode 100644 index 000000000000..f6b0b850b929 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java @@ -0,0 +1,237 @@ +package com.google.cloud.bigquery; + +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; + +import com.google.api.services.bigquery.model.Model; + +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import jdk.internal.joptsimple.internal.Strings; + +import static com.google.common.base.Preconditions.checkNotNull; + + +public class ModelInfo implements Serializable { + + static final Function FROM_PB_FUNCTION = + new Function() { + @Override + public ModelInfo apply(Model pb) { + return ModelInfo.fromPb(pb); + } + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public Model apply(ModelInfo ModelInfo) { + return ModelInfo.toPb(); + } + }; + + private final String etag; + private final ModelId modelId; + private final String description; + private final String modelType; + private final String friendlyName; + private final Long creationTime; + private final Long lastModifiedTime; + private final Long expirationTime; + private final Labels labels; + + + public abstract static class Builder { + + public abstract Builder setDescription(String description); + + public abstract Builder setFriendlyName(String friendlyName); + + public abstract Builder setExpirationTime(Long expirationTime); + + public abstract Builder setLabels(Map labels); + + public abstract Builder setModelId(ModelId modelId); + + abstract Builder setEtag(String etag); + abstract Builder setModelType(String modelType); + abstract Builder setCreationTime(Long creation); + abstract Builder setLastModifiedTime(Long lastModifiedTime); + + + public abstract ModelInfo build(); + } + + static class BuilderImpl extends Builder { + private String etag; + private ModelId modelId; + private String description; + private String modelType; + private String friendlyName; + private Long creationTime; + private Long lastModifiedTime; + private Long expirationTime; + private Labels labels = Labels.ZERO; + + BuilderImpl() {} + + BuilderImpl(ModelInfo modelInfo) { + this.etag = modelInfo.etag; + this.modelId = modelInfo.modelId; + this.description = modelInfo.description; + this.friendlyName = modelInfo.friendlyName; + this.modelType = modelInfo.modelType; + this.creationTime = modelInfo.creationTime; + this.lastModifiedTime = modelInfo.lastModifiedTime; + this.expirationTime = modelInfo.expirationTime; + } + + BuilderImpl(Model modelPb) { + this.modelId = ModelId.fromPb((modelPb.getModelReference()); + if (modelPb.getLastModifiedTime() != null) { + this.setLastModifiedTime(modelPb.getLastModifiedTime().longValue()); + } + this.etag = modelPb.getEtag(); + this.description = modelPb.getDescription(); + this.friendlyName = modelPb.getFriendlyName(); + this.modelType = modelPb.getModelType(); + this.creationTime = modelPb.getCreationTime(); + this.lastModifiedTime = modelPb.getLastModifiedTime(); + this.expirationTime = modelPb.getExpirationTime(); + this.labels = Labels.fromPb(modelPb.getLabels()); + } + + @Override + Builder setEtag(String etag) { + this.etag = etag; + return this; + } + + @Override + public Builder setDescription(String description) { + this.description = description; + return this; + } + + @Override + public Builder setFriendlyName(String friendlyName) { + this.friendlyName = friendlyName; + return this; + } + + @Override + Builder setModelType(String modelType) { + this.modelType = modelType; + return this; + } + + @Override + Builder setCreationTime(Long creationTime) { + this.creationTime = creationTime; + return this; + } + + @Override + Builder setLastModifiedTime(Long lastModifiedTime) { + this.lastModifiedTime = lastModifiedTime; + return this; + } + + @Override + public Builder setExpirationTime(Long expirationTime) { + this.expirationTime = expirationTime; + return this; + } + + @Override + public Builder setModelId(ModelId modelId) { + this.modelId = modelId; + return this; + } + + @Override + public Builder setLabels(Map labels) { + this.labels = Labels.fromUser(labels); + return this; + } + + @Override + public ModelInfo build() { return new ModelInfo(this); } + } + + ModelInfo(BuilderImpl builder) { + this.modelId = checkNotNull(builder.modelId); + this.etag = builder.etag; + this.description = builder.description; + this.friendlyName = builder.friendlyName; + this.creationTime = builder.creationTime; + this.lastModifiedTime = builder.lastModifiedTime; + this.expirationTime = builder.expirationTime; + this.labels = builder.labels; + } + + public String getEtag() { return etag; } + + public ModelId getModelId() { return modelId; } + + public String getDescription() { return description; } + + public String getFriendlyName() { return friendlyName; } + + public Long getCreationTime() { return creationTime; } + + public Long getLastModifiedTime() { return lastModifiedTime; } + + public Long getExpirationTime() { return expirationTime; } + + public Map getLabels() { return labels.userMap(); } + + public Builder toBuilder() { return new BuilderImpl(this); } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("modelId", modelId) + .add("etag", etag) + .add("description", description) + .add("friendlyName", friendlyName) + .add("creationTime", creationTime) + .add("lastModifiedTime", lastModifiedTime) + .add("expirationTime", expirationTime) + .add("labels", labels) + .toString(); + } + + @Override + public int hashcode() { return Objects.hash(modelId); } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj != null + && obj.getClass().equals(ModelInfo.class) + && Objects.equals(toPb(), ((ModelInfo) obj).toPb()); + } + + public static Builder newBuilder(ModelId modelId) { + return new BuilderImpl().setModelId(modelId); + } + + public static ModelInfo of(ModelId modelId) { + return newBuilder(modelId).build(); + } + + ModelInfo setProjectId(String projectId) { + if (Strings.isNullOrEmpty(getModelId().getProject())) { + return toBuilder().setModelId(getModelId().setProjectId(projectId)).build(); + } + return this; + } + + Model toPb() { + Model modelPb = + } + + static ModelInfo fromPb(Model modelPb) { return new BuilderImpl(modelPb).build(); } + +} From b890c81334a333dd17ea381f574e7cf3213e335b Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Mon, 22 Apr 2019 16:10:31 -0700 Subject: [PATCH 02/13] more impl --- .../com/google/cloud/bigquery/BigQuery.java | 161 ++++++++++++++++++ .../google/cloud/bigquery/BigQueryImpl.java | 135 +++++++++++++++ .../java/com/google/cloud/bigquery/Model.java | 144 +++++++++++++++- .../com/google/cloud/bigquery/ModelId.java | 2 +- .../com/google/cloud/bigquery/ModelInfo.java | 3 + 5 files changed, 439 insertions(+), 6 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java index 1af420294429..9813255b1e7b 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java @@ -116,6 +116,41 @@ public String getSelector() { } } + /** + * Fields of a BigQuery Model resource. + * + * @see Model + * Resource + */ + enum ModelField implements FieldSelector { + CREATION_TIME("creationTime"), + DESCRIPTION("description"), + ETAG("etag"), + EXPIRATION_TIME("expirationTime"), + FRIENDLY_NAME("friendlyName"), + LABELS("labels"), + LAST_MODIFIED_TIME("lastModifiedTime"), + LOCATION("location"), + MODEL_REFERENCE("modelReference"), + TIME_PARTITIONING("timePartitioning"), + TYPE("modelType"), + VIEW("view"); + + static final List REQUIRED_FIELDS = + ImmutableList.of(MODEL_REFERENCE); + + private final String selector; + + ModelField(String selector) { + this.selector = selector; + } + + @Override + public String getSelector() { + return selector; + } + } + /** * Fields of a BigQuery Job resource. * @@ -211,6 +246,27 @@ public static DatasetDeleteOption deleteContents() { } } + /** Class for specifying table list options. */ + class ModelListOption extends Option { + + private static final long serialVersionUID = 8660294969063322498L; + + private ModelListOption(BigQueryRpc.Option option, Object value) { + super(option, value); + } + + /** Returns an option to specify the maximum number of models returned per page. */ + public static ModelListOption pageSize(long pageSize) { + checkArgument(pageSize >= 0); + return new ModelListOption(BigQueryRpc.Option.MAX_RESULTS, pageSize); + } + + /** Returns an option to specify the page token from which to start listing models. */ + public static ModelListOption pageToken(String pageToken) { + return new ModelListOption(BigQueryRpc.Option.PAGE_TOKEN, pageToken); + } + } + /** Class for specifying table list options. */ class TableListOption extends Option { @@ -253,6 +309,26 @@ public static TableOption fields(TableField... fields) { } } + /** Class for specifying table get, create and update options. */ + class ModelOption extends Option { + + private static final long serialVersionUID = -1723870134095226772L; + + private ModelOption(BigQueryRpc.Option option, Object value) { + super(option, value); + } + + /** + * Returns an option to specify the model's fields to be returned by the RPC call. If this + * option is not provided all model's fields are returned. {@code ModelOption.fields} can be + * used to specify only the fields of interest. + */ + public static ModelOption fields(ModelField... fields) { + return new ModelOption( + BigQueryRpc.Option.FIELDS, Helper.selector(ModelField.REQUIRED_FIELDS, fields)); + } + } + /** Class for specifying table data list options. */ class TableDataListOption extends Option { @@ -714,6 +790,29 @@ public int hashCode() { */ boolean delete(TableId tableId); + /** + * Deletes the requested model. + * + *

Example of deleting a model. + * + *

{@code
+   * String projectId = "my_project_id";
+   * String datasetName = "my_dataset_name";
+   * String tableName = "my_model_name";
+   * ModelId modelId = ModelId.of(projectId, datasetName, modelName);
+   * boolean deleted = bigquery.delete(modelId);
+   * if (deleted) {
+   *   // the model was deleted
+   * } else {
+   *   // the model was not found
+   * }
+   * }
+ * + * @return {@code true} if model was deleted, {@code false} if it was not found + * @throws BigQueryException upon failure + */ + boolean delete(ModelId modelId); + /** * Updates dataset information. * @@ -774,6 +873,41 @@ public int hashCode() { */ Table update(TableInfo tableInfo, TableOption... options); + /** + * Updates model information. + * + *

Example of updating a model by changing its description. + * + *

{@code
+   * String datasetName = "my_dataset_name";
+   * String modelName = "my_model_name";
+   * String newDescription = "new_description";
+   * Model beforeModel = bigquery.getModel(datasetName, modelName);
+   * ModelInfo modelInfo = beforeModel.toBuilder()
+   *     .setDescription(newDescription)
+   *     .build();
+   * Model afterModel = bigquery.update(moddelInfo);
+   * }
+ * + *

Example of updating a model by changing its expiration. + * + *

{@code
+   * String datasetName = "my_dataset_name";
+   * String modelName = "my_model_name";
+   * Model beforeModel = bigquery.getModel(datasetName, modelName);
+   *
+   * // Set model to expire 5 days from now.
+   * long expirationMillis = DateTime.now().plusDays(5).getMillis();
+   * ModelInfo modelInfo = beforeModel.toBuilder()
+   *         .setExpirationTime(expirationMillis)
+   *         .build();
+   * Model afterModel = bigquery.update(modelInfo);
+   * }
+ * + * @throws BigQueryException upon failure + */ + Model update(ModelInfo modelInfo, ModelOption... options); + /** * Returns the requested table or {@code null} if not found. * @@ -806,6 +940,23 @@ public int hashCode() { */ Table getTable(TableId tableId, TableOption... options); + /** + * Returns the requested model or {@code null} if not found. + * + *

Example of getting a model. + * + *

{@code
+   * String projectId = "my_project_id";
+   * String datasetName = "my_dataset_name";
+   * String modelName = "my_model_name";
+   * ModelId modelId = ModelId.of(projectId, datasetName, tableName);
+   * Model model = bigquery.getModel(modelId);
+   * }
+ * + * @throws BigQueryException upon failure + */ + Model getModel(ModelId tableId, ModelOption... options); + /** * Lists the tables in the dataset. This method returns partial information on each table: ({@link * Table#getTableId()}, {@link Table#getFriendlyName()}, {@link Table#getGeneratedId()} and type, @@ -848,6 +999,16 @@ public int hashCode() { */ Page listTables(DatasetId datasetId, TableListOption... options); + /** + * Lists the models in the dataset. + */ + Page listModels(String datasetId, ModelListOption... options); + + /** + * Lists the models in the dataset. + */ + Page listModels(DatasetId datasetId, ModelListOption... options); + /** * @param tableId * @return A list of the partition ids present in the partitioned table diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java index 09a16fa629ef..c1fd7246e328 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java @@ -406,6 +406,31 @@ public Boolean call() { } } + @Override + public boolean delete(ModelId modelId) { + final ModelId completeModelId = modelId.setProjectId( + Strings.isNullOrEmpty(modelId.getProject()) + ? getOptions.getProjectId() + : modelId.getProject()); + try { + return runWithRetries( + new Callable() { + @Override + public Boolean call() { + return bigQueryRpc.deleteModel( + completeModelId.getProject(), + completeModelId.getDataset(), + completeModelId.getModel()); + } + }, + getOptions().getRetrySettings(), + EXCEPTION_HANDLER, + getOptions().getClock()); + } catch (RetryHelper.RetryHelperException e) { + throw BigQueryException.translateAndThrow(e); + } + } + @Override public Dataset update(DatasetInfo datasetInfo, DatasetOption... options) { final com.google.api.services.bigquery.model.Dataset datasetPb = @@ -457,6 +482,34 @@ public com.google.api.services.bigquery.model.Table call() { } } + @Override + public Model update(ModelInfo modelInfo, ModelOption... options) { + final com.google.api.services.bigquery.model.Model modelPb = + modelInfo + .setProjectId( + Strings.isNullOrEmpty(modelInfo.getModelId().getProject()) + ? getOptions().getProjectId() + : modelInfo.getModelId().getProject()) + .toPb(); + final Map optionsMap = optionMap(options); + try { + return Model.fromPb( + this, + runWithRetries( + new Callable() { + @Override + public com.google.api.services.bigquery.model.Model call() { + return bigQueryRpc.patch(modelPb, optionsMap); + } + }, + getOptions().getRetrySettings(), + EXCEPTION_HANDLER, + getOptions().getClock())); + } catch (RetryHelper.RetryHelperException e) { + throw BigQueryException.translateAndThrow(e); + } + } + @Override public Table getTable(final String datasetId, final String tableId, TableOption... options) { return getTable(TableId.of(datasetId, tableId), options); @@ -496,6 +549,39 @@ public com.google.api.services.bigquery.model.Table call() { } } + @Override + public Model getModel(ModelId modelId, ModelOption... options) { + final ModelId completeModelId = + modelId.setProjectId( + Strings.isNullOrEmpty(modelId.getProject()) + ? getOptions().getProjectId() + : modelId.getProject()); + final Map optionsMap = optionMap(options); + try { + com.google.api.services.bigquery.model.Model answer = + runWithRetries( + new Callable() { + @Override + public com.google.api.services.bigquery.model.Model call() { + return bigQueryRpc.getModel( + completeModelId.getProject(), + completeModelId.getDataset(), + completeModelId.getModel(), + optionsMap); + } + }, + getOptions().getRetrySettings(), + EXCEPTION_HANDLER, + getOptions().getClock()); + if (getOptions().getThrowNotFound() && answer == null) { + throw new BigQueryException(HTTP_NOT_FOUND, "Model not found"); + } + return answer == null ? null : Model.fromPb(this, answer); + } catch (RetryHelper.RetryHelperException e) { + throw BigQueryException.translateAndThrow(e); + } + } + @Override public Page
listTables(String datasetId, TableListOption... options) { return listTables( @@ -508,6 +594,18 @@ public Page
listTables(DatasetId datasetId, TableListOption... options) { return listTables(completeDatasetId, getOptions(), optionMap(options)); } + @Override + public Page listModels(String datasetId, ModelListOption... options) { + return listModels( + DatasetId.of(getOptions().getProjectId(), datasetId), getOptions(), optionMap(options)); + } + + @Override + public Page listModels(DatasetId datasetId, ModelListOption... options) { + DatasetId completeDatasetId = datasetId.setProjectId(getOptions().getProjectId()); + return listTables(completeDatasetId, getOptions(), optionMap(options)); + } + @Override public List listPartitions(TableId tableId) { List partitions = new ArrayList(); @@ -565,6 +663,43 @@ public Table apply(com.google.api.services.bigquery.model.Table table) { } } + private static Page listModels( + final DatasetId datasetId, + final BigQueryOptions serviceOptions, + final Map optionsMap) { + try { + Tuple> result = + runWithRetries( + new Callable< + Tuple>>() { + @Override + public Tuple> + call() { + return serviceOptions + .getBigQueryRpcV2() + .listModels(datasetId.getProject(), datasetId.getDataset(), optionsMap); + } + }, + serviceOptions.getRetrySettings(), + EXCEPTION_HANDLER, + serviceOptions.getClock()); + String cursor = result.x(); + Iterable models = + Iterables.transform( + result.y(), + new Function() { + @Override + public Model apply(com.google.api.services.bigquery.model.Model model) { + return Model.fromPb(serviceOptions.getService(), model); + } + }); + return new PageImpl<>( + new TablePageFetcher(datasetId, serviceOptions, cursor, optionsMap), cursor, models); + } catch (RetryHelper.RetryHelperException e) { + throw BigQueryException.translateAndThrow(e); + } + } + @Override public InsertAllResponse insertAll(InsertAllRequest request) { final TableId tableId = diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java index 9ccc27d58d21..4dcf964006e8 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java @@ -1,6 +1,15 @@ package com.google.cloud.bigquery; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.api.services.bigquery.model.ModelDefinition.ModelOptions; +import com.google.cloud.bigquery.BigQuery.ModelOption; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.Map; +import java.util.Objects; + /** * A Google BigQuery ML Model. * @@ -11,23 +20,148 @@ */ public class Model extends ModelInfo { - private final BigQUeryOptions options; + private final BigQueryOptions options; private transient BigQuery bigquery; public static class Builder extends ModelInfo.Builder { - private final BigQUery bigquery; + private final BigQuery bigquery; private final ModelInfo.BuilderImpl infoBuilder; - Builder(BigQuery bigquery, ModelId modelId, ModelDefinition definition) { + Builder(BigQuery bigquery, ModelId modelId) { this.bigquery = bigquery; this.infoBuilder = new ModelInfo.BuilderImpl(); - this.infoBuilder.setModelId(modelId).setDefinition(definition); } + + Builder(Model model) { + this.bigquery = model.bigquery; + this.infoBuilder = new ModelInfo.BuilderImpl(model); + } + + @Override + Builder setCreationTime(Long creationTime) { + infoBuilder.setCreationTime(creationTime); + return this; + } + + @Override + public Builder setDescription(String description) { + infoBuilder.setDescription(description); + return this; + } + + @Override + Builder setModelType(String modelType) { + infoBuilder.setModelType(modelType); + return this; + } + + @Override + Builder setEtag(String etag) { + infoBuilder.setEtag(etag); + return this; + } + + @Override + public Builder setExpirationTime(Long expirationTime) { + infoBuilder.setExpirationTime(expirationTime); + return this; + } + + @Override + public Builder setFriendlyName(String friendlyName) { + infoBuilder.setFriendlyName(friendlyName); + return this; + } + + @Override + Builder setLastModifiedTime(Long lastModifiedTime) { + infoBuilder.setLastModifiedTime(lastModifiedTime); + return this; + } + + @Override + public Builder setModelId(ModelId modelId) { + infoBuilder.setModelId(modelId); + return this; + } + + @Override + public Builder setLabels(Map labels) { + infoBuilder.setLabels(labels); + return this; + } + + public Model build() { return new Model(bigquery, infoBuilder); } + } + + Model(BigQuery bigquery, ModelInfo.BuilderImpl infoBuilder) { + super(infoBuilder); + this.bigquery = checkNotNull(bigquery); + this.options = bigquery.getOptions(); + } + + /** Check if this model exists. + * + * @return {@code true} if this table exists, {@code false} otherwise + * @throws BigQueryException upon failure + */ + public boolean exists() { return bigquery.getModel(getModelId(), ModelOption.fields()) != null; } + + /** + * Fetches current model's later information. Returns {@code null} if the model does not exist. + * + * @param options model options + * @return a {@code Model} object with latest information or {@code null} if not found + * @throws BigQueryException upon failure + */ + public Model reload(ModelOption... options) { return bigquery.getModel(getModelId(), options); } + + /** + * Updates the model's information with this model's information. Dataset and model identifiers + * cannot be updates. A new {@code Model} object is returned. + * + * @param options dataset options + * @return a {@code Model} object with updated information + * @throws BigQueryException upon failure + */ + public Model update(ModelOption... options) { return bigquery.update(this, options); } + + /** + * Deletes this model. + * + * @return {@code true} if model was deleted, {@code false} if it was not found + * @throws BigQueryException upon failure + */ + public boolean delete() { return bigquery.delete(getModelId()); } + + /** Return's the model's {@code BigQuery} object used to issuie requests. **/ + public BigQuery getBigQuery() { return bigquery; } + + @Override + public Builder toBuilder() { return new Builder(this); } + + @Override + public final boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || !obj.getClass().equals(Model.class)) { + return false; + } + Model other = (Model) obj; + return Objects.equals(toPb(), other.toPb()) && Objects.equals(options, other.options); } + @Override + public final int hashCode() { return Objects.hash(super.hashCode(), options); } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + this.bigquery = options.getService(); + } static Model fromPb(BigQuery bigquery, com.google.api.services.bigquery.model.Model modelPb) { - return new Table(bigquery, new ModelInfo.BuilderImpl(modelPb)); + return new Model(bigquery, new ModelInfo.BuilderImpl(modelPb)); } } diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java index 2d90f1c41f48..1b00f6dc20a3 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java @@ -69,7 +69,7 @@ public static ModelId of(String project, String dataset, String model) { return new ModelId(checkNotNull(project), checkNotNull(dataset), checkNotNull(model)); } - /** Creates a model identity given data and table identifiers. **/ + /** Creates a model identity given dataset and model identifiers. **/ public static ModelId of(String dataset, String model) { return new ModelId(null, checkNotNull(dataset), checkNotNull(model)); } diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java index f6b0b850b929..ad4f8a5e1120 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java @@ -174,6 +174,8 @@ public Builder setLabels(Map labels) { public ModelId getModelId() { return modelId; } + public String getModelType() { return modelType; } + public String getDescription() { return description; } public String getFriendlyName() { return friendlyName; } @@ -193,6 +195,7 @@ public String toString() { return MoreObjects.toStringHelper(this) .add("modelId", modelId) .add("etag", etag) + .add("modelType", modelType) .add("description", description) .add("friendlyName", friendlyName) .add("creationTime", creationTime) From 2a01f8d4c3dbc729bd2cb4539cbd314e65097104 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Wed, 24 Apr 2019 09:34:30 -0700 Subject: [PATCH 03/13] more modelling --- .../java/com/google/cloud/bigquery/Model.java | 16 +++++ .../com/google/cloud/bigquery/ModelId.java | 2 - .../com/google/cloud/bigquery/ModelInfo.java | 30 +++++++++- .../google/cloud/bigquery/ModelIdTest.java | 58 +++++++++++++++++++ 4 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java index 4dcf964006e8..368648993bdd 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.google.cloud.bigquery; diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java index 1b00f6dc20a3..1c32b6a26ba3 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java @@ -14,8 +14,6 @@ * limitations under the License. */ - - package com.google.cloud.bigquery; import java.io.Serializable; diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java index ad4f8a5e1120..d7c2088873c1 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.google.cloud.bigquery; import java.io.Serializable; @@ -87,7 +103,7 @@ static class BuilderImpl extends Builder { } BuilderImpl(Model modelPb) { - this.modelId = ModelId.fromPb((modelPb.getModelReference()); + this.modelId = ModelId.fromPb(modelPb.getModelReference()); if (modelPb.getLastModifiedTime() != null) { this.setLastModifiedTime(modelPb.getLastModifiedTime().longValue()); } @@ -232,7 +248,17 @@ ModelInfo setProjectId(String projectId) { } Model toPb() { - Model modelPb = + Model modelPb = new Model(); + modelPb.setModelReference(modelId.toPb()); + modelPb.setEtag(etag); + modelPb.setModelType(modelType); + modelPb.setDescription(description); + modelPb.setFriendlyName(friendlyName); + modelPb.setCreationTime(creationTime); + modelPb.setLastModifiedTime(lastModifiedTime); + modelPb.setExpirationTime(expirationTime); + modelPb.setLabels(labels.toPb()); + return modelPb; } static ModelInfo fromPb(Model modelPb) { return new BuilderImpl(modelPb).build(); } diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java new file mode 100644 index 000000000000..5ee3a0d1e4a9 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.bigquery; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class ModelIdTest { + + public static final ModelId MODEL = ModelId.of("dataset", "model"); + public static final ModelId MODEL_COMPLETE = ModelId.of("project", "dataset", "model"); + + @Test + public void testOf() { + assertEquals(null, MODEL.getProject()); + assertEquals("dataset", MODEL.getDataset()); + assertEquals("model", MODEL.getModel()); + + assertEquals("project", MODEL_COMPLETE.getProject()); + assertEquals("dataset", MODEL_COMPLETE.getDataset()); + assertEquals("model", MODEL_COMPLETE.getModel()); + } + + @Test + public void testToPbAndFromPb() { + compareModelIds(MODEL, ModelId.fromPb(MODEL.toPb())); + compareModelIds(MODEL_COMPLETE, ModelId.fromPb(MODEL_COMPLETE.toPb())); + } + + @Test + public void testSetProjectId() { + ModelId differentProjectTable = ModelId.of("differentProject", "dataset", "table"); + assertEquals(differentProjectTable, MODEL.setProjectId("differentProject")); + } + + private void compareModelIds(ModelId expected, ModelId value) { + assertEquals(expected, value); + assertEquals(expected.getProject(), value.getProject()); + assertEquals(expected.getDataset(), value.getDataset()); + assertEquals(expected.hashCode(), value.hashCode()); + } + +} \ No newline at end of file From b4cd4e681a1c67661ba054bab60e034a0c22537d Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Wed, 24 Apr 2019 12:36:42 -0700 Subject: [PATCH 04/13] more modelling --- .../google-cloud-bigquery/pom.xml | 2 +- .../google/cloud/bigquery/BigQueryImpl.java | 37 +++++++-- .../com/google/cloud/bigquery/ModelInfo.java | 10 ++- .../cloud/bigquery/spi/v2/BigQueryRpc.java | 31 +++++++ .../bigquery/spi/v2/HttpBigQueryRpc.java | 69 +++++++++++++++ .../google/cloud/bigquery/ModelIdTest.java | 8 +- .../google/cloud/bigquery/ModelInfoTest.java | 83 +++++++++++++++++++ 7 files changed, 229 insertions(+), 11 deletions(-) create mode 100644 google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java diff --git a/google-cloud-clients/google-cloud-bigquery/pom.xml b/google-cloud-clients/google-cloud-bigquery/pom.xml index 13bf453979d9..804e7729fe96 100644 --- a/google-cloud-clients/google-cloud-bigquery/pom.xml +++ b/google-cloud-clients/google-cloud-bigquery/pom.xml @@ -12,7 +12,7 @@ com.google.cloud google-cloud-clients - 0.88.1-alpha-SNAPSHOT + 0.88.0-alpha google-cloud-bigquery diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java index c1fd7246e328..ef8b4763a53d 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java @@ -101,6 +101,30 @@ public Page
getNextPage() { } } + private static class ModelPageFetcher implements NextPageFetcher { + + private static final long serialVersionUID = 8611248811504201187L; + private final Map requestOptions; + private final BigQueryOptions serviceOptions; + private final DatasetId datasetId; + + ModelPageFetcher( + DatasetId datasetId, + BigQueryOptions serviceOptions, + String cursor, + Map optionMap) { + this.requestOptions = + PageImpl.nextRequestOptions(BigQueryRpc.Option.PAGE_TOKEN, cursor, optionMap); + this.serviceOptions = serviceOptions; + this.datasetId = datasetId; + } + + @Override + public Page getNextPage() { + return listModels(datasetId, serviceOptions, requestOptions); + } + } + private static class JobPageFetcher implements NextPageFetcher { private static final long serialVersionUID = 8536533282558245472L; @@ -408,9 +432,10 @@ public Boolean call() { @Override public boolean delete(ModelId modelId) { - final ModelId completeModelId = modelId.setProjectId( + final ModelId completeModelId = + modelId.setProjectId( Strings.isNullOrEmpty(modelId.getProject()) - ? getOptions.getProjectId() + ? getOptions().getProjectId() : modelId.getProject()); try { return runWithRetries( @@ -603,7 +628,7 @@ public Page listModels(String datasetId, ModelListOption... options) { @Override public Page listModels(DatasetId datasetId, ModelListOption... options) { DatasetId completeDatasetId = datasetId.setProjectId(getOptions().getProjectId()); - return listTables(completeDatasetId, getOptions(), optionMap(options)); + return listModels(completeDatasetId, getOptions(), optionMap(options)); } @Override @@ -671,9 +696,9 @@ private static Page listModels( Tuple> result = runWithRetries( new Callable< - Tuple>>() { + Tuple>>() { @Override - public Tuple> + public Tuple> call() { return serviceOptions .getBigQueryRpcV2() @@ -694,7 +719,7 @@ public Model apply(com.google.api.services.bigquery.model.Model model) { } }); return new PageImpl<>( - new TablePageFetcher(datasetId, serviceOptions, cursor, optionsMap), cursor, models); + new ModelPageFetcher(datasetId, serviceOptions, cursor, optionsMap), cursor, models); } catch (RetryHelper.RetryHelperException e) { throw BigQueryException.translateAndThrow(e); } diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java index d7c2088873c1..c009d30283ab 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java @@ -16,6 +16,7 @@ package com.google.cloud.bigquery; +import com.google.common.base.Strings; import java.io.Serializable; import java.util.Map; import java.util.Objects; @@ -24,7 +25,6 @@ import com.google.common.base.Function; import com.google.common.base.MoreObjects; -import jdk.internal.joptsimple.internal.Strings; import static com.google.common.base.Preconditions.checkNotNull; @@ -46,6 +46,9 @@ public Model apply(ModelInfo ModelInfo) { } }; + private static final long serialVersionUID = 609769793337719407L; + + private final String etag; private final ModelId modelId; private final String description; @@ -57,6 +60,7 @@ public Model apply(ModelInfo ModelInfo) { private final Labels labels; + /** A builder for {@code ModelInfo} objects. **/ public abstract static class Builder { public abstract Builder setDescription(String description); @@ -74,7 +78,6 @@ public abstract static class Builder { abstract Builder setCreationTime(Long creation); abstract Builder setLastModifiedTime(Long lastModifiedTime); - public abstract ModelInfo build(); } @@ -178,6 +181,7 @@ public Builder setLabels(Map labels) { ModelInfo(BuilderImpl builder) { this.modelId = checkNotNull(builder.modelId); this.etag = builder.etag; + this.modelType = builder.modelType; this.description = builder.description; this.friendlyName = builder.friendlyName; this.creationTime = builder.creationTime; @@ -222,7 +226,7 @@ public String toString() { } @Override - public int hashcode() { return Objects.hash(modelId); } + public int hashCode() { return Objects.hash(modelId); } @Override public boolean equals(Object obj) { diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java index 27a1fe12351d..c8319a8dee53 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java @@ -20,6 +20,7 @@ import com.google.api.services.bigquery.model.Dataset; import com.google.api.services.bigquery.model.GetQueryResultsResponse; import com.google.api.services.bigquery.model.Job; +import com.google.api.services.bigquery.model.Model; import com.google.api.services.bigquery.model.Table; import com.google.api.services.bigquery.model.TableDataInsertAllRequest; import com.google.api.services.bigquery.model.TableDataInsertAllResponse; @@ -156,6 +157,36 @@ Tuple> listTables( */ boolean deleteTable(String projectId, String datasetId, String tableId); + /** + * Updates table information. + * + * @throws BigQueryException upon failure + */ + Model patch(Model model, Map options); + + /** + * Returns the requested model or {@code null} if not found. + * + * @throws BigQueryException upon failure + */ + Model getModel(String projectId, String datasetId, String modelId, Map options); + + /** + * Lists the dataset's models. Partial information is returned on a model. + * + * @throws BigQueryException upon failure + */ + Tuple> listModels( + String projectId, String dataset, Map options); + + /** + * Delete the requested model. + * + * @return {@code true} if model was deleted, {@code false} if it was not found + * @throws BigQueryException upon failure + */ + boolean deleteModel(String projectId, String datasetId, String modelId); + /** * Sends an insert all request. * diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java index 70ade809b8ee..638eb9f823d4 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java @@ -41,6 +41,9 @@ import com.google.api.services.bigquery.model.Job; import com.google.api.services.bigquery.model.JobList; import com.google.api.services.bigquery.model.JobStatus; +import com.google.api.services.bigquery.model.ListModelsResponse; +import com.google.api.services.bigquery.model.Model; +import com.google.api.services.bigquery.model.ModelReference; import com.google.api.services.bigquery.model.Table; import com.google.api.services.bigquery.model.TableDataInsertAllRequest; import com.google.api.services.bigquery.model.TableDataInsertAllResponse; @@ -300,6 +303,72 @@ public boolean deleteTable(String projectId, String datasetId, String tableId) { } } + @Override + public Model patch(Model model, Map options) { + try { + // unset the type, as it is output only + ModelReference reference = model.getModelReference(); + return bigquery + .models() + .patch(reference.getProjectId(), reference.getDatasetId(), reference.getModelId(), model) + .setFields(Option.FIELDS.getString(options)) + .execute(); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public Model getModel(String projectId, String datasetId, String modelId, + Map options) { + try { + return bigquery + .models() + .get(projectId, datasetId, modelId) + .setFields(Option.FIELDS.getString(options)) + .execute(); + } catch (IOException ex) { + BigQueryException serviceException = translate(ex); + if (serviceException.getCode() == HTTP_NOT_FOUND) { + return null; + } + throw serviceException; + } + } + + @Override + public Tuple> listModels( + String projectId, String datasetId, Map options) { + try { + ListModelsResponse modelList = + bigquery + .models() + .list(projectId, datasetId) + .setMaxResults(Option.MAX_RESULTS.getLong(options)) + .setPageToken(Option.PAGE_TOKEN.getString(options)) + .execute(); + Iterable models = modelList.getModels(); + return Tuple.of( + modelList.getNextPageToken(), models); + } catch (IOException ex) { + throw translate(ex); + } + } + + @Override + public boolean deleteModel(String projectId, String datasetId, String modelId) { + try { + bigquery.models().delete(projectId, datasetId, modelId).execute(); + return true; + } catch (IOException ex) { + BigQueryException serviceException = translate(ex); + if (serviceException.getCode() == HTTP_NOT_FOUND) { + return false; + } + throw serviceException; + } + } + @Override public TableDataInsertAllResponse insertAll( String projectId, String datasetId, String tableId, TableDataInsertAllRequest request) { diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java index 5ee3a0d1e4a9..a3adc0207350 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java @@ -36,6 +36,12 @@ public void testOf() { assertEquals("model", MODEL_COMPLETE.getModel()); } + @Test + public void testEquals() { + compareModelIds(MODEL, ModelId.of("dataset", "model")); + compareModelIds(MODEL_COMPLETE, ModelId.of("project", "dataset", "model")); + } + @Test public void testToPbAndFromPb() { compareModelIds(MODEL, ModelId.fromPb(MODEL.toPb())); @@ -44,7 +50,7 @@ public void testToPbAndFromPb() { @Test public void testSetProjectId() { - ModelId differentProjectTable = ModelId.of("differentProject", "dataset", "table"); + ModelId differentProjectTable = ModelId.of("differentProject", "dataset", "model"); assertEquals(differentProjectTable, MODEL.setProjectId("differentProject")); } diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java new file mode 100644 index 000000000000..525974eb585c --- /dev/null +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigquery; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +public class ModelInfoTest { + + private static final ModelId MODEL_ID = ModelId.of("dataset", "model"); + private static final String ETAG = "etag"; + private static final Long CREATION_TIME = 10L; + private static final Long LAST_MODIFIED_TIME = 20L; + private static final Long EXPIRATION_TIME = 30L; + private static final String DESCRIPTION = "description"; + private static final String FRIENDLY_NAME = "friendlyname"; + + private static final ModelInfo MODEL_INFO = + ModelInfo.newBuilder(MODEL_ID) + .setEtag(ETAG) + .setCreationTime(CREATION_TIME) + .setExpirationTime(EXPIRATION_TIME) + .setLastModifiedTime(LAST_MODIFIED_TIME) + .setDescription(DESCRIPTION) + .setFriendlyName(FRIENDLY_NAME) + .build(); + + + @Test + public void testToBuilder() { + compareModelInfo(MODEL_INFO, MODEL_INFO.toBuilder().build()); + } + + @Test + public void testToBuilderIncomplete() { + ModelInfo modelInfo = ModelInfo.of(MODEL_ID); + assertEquals(modelInfo, modelInfo.toBuilder().build()); + } + + @Test + public void testBuilder() { + assertEquals(ETAG, MODEL_INFO.getEtag()); + assertEquals(CREATION_TIME, MODEL_INFO.getCreationTime()); + assertEquals(LAST_MODIFIED_TIME, MODEL_INFO.getLastModifiedTime()); + assertEquals(EXPIRATION_TIME, MODEL_INFO.getExpirationTime()); + assertEquals(DESCRIPTION, MODEL_INFO.getDescription()); + assertEquals(FRIENDLY_NAME, MODEL_INFO.getFriendlyName()); + } + + @Test + public void testToAndFromPb() { + compareModelInfo(MODEL_INFO, ModelInfo.fromPb(MODEL_INFO.toPb())); + } + + + private void compareModelInfo(ModelInfo expected, ModelInfo value) { + assertEquals(expected, value); + assertEquals(expected.getModelId(), value.getModelId()); + assertEquals(expected.getEtag(), value.getEtag()); + assertEquals(expected.getCreationTime(), value.getCreationTime()); + assertEquals(expected.getLastModifiedTime(), value.getLastModifiedTime()); + assertEquals(expected.getExpirationTime(), value.getExpirationTime()); + assertEquals(expected.getDescription(), value.getDescription()); + assertEquals(expected.getFriendlyName(), value.getFriendlyName()); + assertEquals(expected.getLabels(), value.getLabels()); + assertEquals(expected.hashCode(), value.hashCode()); + } +} From cb8961fdd0c2509eafe986a1bed73c16dc4c7647 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Wed, 24 Apr 2019 14:29:45 -0700 Subject: [PATCH 05/13] model testing --- .../testing/RemoteBigQueryHelper.java | 5 + .../google/cloud/bigquery/ModelInfoTest.java | 16 +++ .../com/google/cloud/bigquery/ModelTest.java | 21 +++ .../cloud/bigquery/it/ITBigQueryTest.java | 131 +++++++++++++----- 4 files changed, 137 insertions(+), 36 deletions(-) create mode 100644 google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/testing/RemoteBigQueryHelper.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/testing/RemoteBigQueryHelper.java index f28c835d61f3..672b7e7c74a1 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/testing/RemoteBigQueryHelper.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/testing/RemoteBigQueryHelper.java @@ -42,6 +42,7 @@ public class RemoteBigQueryHelper { private static final Logger log = Logger.getLogger(RemoteBigQueryHelper.class.getName()); private static final String DATASET_NAME_PREFIX = "gcloud_test_dataset_temp_"; + private static final String MODEL_NAME_PREFIX = "model_"; private final BigQueryOptions options; private static final int connectTimeout = 60000; @@ -71,6 +72,10 @@ public static String generateDatasetName() { return DATASET_NAME_PREFIX + UUID.randomUUID().toString().replace('-', '_'); } + public static String generateModelName() { + return MODEL_NAME_PREFIX + UUID.randomUUID().toString().replace('-', '_'); + } + /** * Creates a {@code RemoteBigQueryHelper} object for the given project id and JSON key input * stream. diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java index 525974eb585c..70a6fe701b74 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java @@ -62,11 +62,27 @@ public void testBuilder() { assertEquals(FRIENDLY_NAME, MODEL_INFO.getFriendlyName()); } + @Test + public void testOf() { + ModelInfo modelInfo = ModelInfo.of(MODEL_ID); + assertEquals(MODEL_ID, modelInfo.getModelId()); + assertNull(modelInfo.getEtag()); + assertNull(modelInfo.getCreationTime()); + assertNull(modelInfo.getLastModifiedTime()); + assertNull(modelInfo.getExpirationTime()); + assertNull(modelInfo.getDescription()); + assertNull(modelInfo.getFriendlyName()); + } + @Test public void testToAndFromPb() { compareModelInfo(MODEL_INFO, ModelInfo.fromPb(MODEL_INFO.toPb())); } + @Test + public void testSetProjectId() { + assertEquals("project", MODEL_INFO.setProjectId("project").getModelId().getProject()); + } private void compareModelInfo(ModelInfo expected, ModelInfo value) { assertEquals(expected, value); diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java new file mode 100644 index 000000000000..9ff55829b600 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java @@ -0,0 +1,21 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.bigquery; + +public class ModelTest { + +} diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java index 0ed59061442d..aa3e6ce5305c 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java @@ -60,6 +60,9 @@ import com.google.cloud.bigquery.JobStatistics.LoadStatistics; import com.google.cloud.bigquery.LegacySQLTypeName; import com.google.cloud.bigquery.LoadJobConfiguration; +import com.google.cloud.bigquery.Model; +import com.google.cloud.bigquery.ModelId; +import com.google.cloud.bigquery.ModelInfo; import com.google.cloud.bigquery.QueryJobConfiguration; import com.google.cloud.bigquery.QueryParameterValue; import com.google.cloud.bigquery.Schema; @@ -89,6 +92,7 @@ import java.math.BigDecimal; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.rmi.Remote; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -118,6 +122,7 @@ public class ITBigQueryTest { private static final String DATASET = RemoteBigQueryHelper.generateDatasetName(); private static final String DESCRIPTION = "Test dataset"; private static final String OTHER_DATASET = RemoteBigQueryHelper.generateDatasetName(); + private static final String MODEL_DATASET = RemoteBigQueryHelper.generateDatasetName(); private static final Map LABELS = ImmutableMap.of( "example-label1", "example-value1", @@ -149,13 +154,13 @@ public class ITBigQueryTest { .build(); private static final Field RECORD_FIELD_SCHEMA = Field.newBuilder( - "RecordField", - LegacySQLTypeName.RECORD, - TIMESTAMP_FIELD_SCHEMA, - STRING_FIELD_SCHEMA, - INTEGER_ARRAY_FIELD_SCHEMA, - BOOLEAN_FIELD_SCHEMA, - BYTES_FIELD_SCHEMA) + "RecordField", + LegacySQLTypeName.RECORD, + TIMESTAMP_FIELD_SCHEMA, + STRING_FIELD_SCHEMA, + INTEGER_ARRAY_FIELD_SCHEMA, + BOOLEAN_FIELD_SCHEMA, + BYTES_FIELD_SCHEMA) .setMode(Field.Mode.REQUIRED) .setDescription("RecordDescription") .build(); @@ -261,7 +266,8 @@ public class ITBigQueryTest { private static BigQuery bigquery; private static Storage storage; - @Rule public Timeout globalTimeout = Timeout.seconds(300); + @Rule + public Timeout globalTimeout = Timeout.seconds(300); @BeforeClass public static void beforeClass() throws InterruptedException, TimeoutException { @@ -279,9 +285,11 @@ public static void beforeClass() throws InterruptedException, TimeoutException { DatasetInfo info = DatasetInfo.newBuilder(DATASET).setDescription(DESCRIPTION).setLabels(LABELS).build(); bigquery.create(info); + DatasetInfo info2 = DatasetInfo.newBuilder(MODEL_DATASET).setDescription("java model lifecycle").build(); + bigquery.create(info2); LoadJobConfiguration configuration = LoadJobConfiguration.newBuilder( - TABLE_ID, "gs://" + BUCKET + "/" + JSON_LOAD_FILE, FormatOptions.json()) + TABLE_ID, "gs://" + BUCKET + "/" + JSON_LOAD_FILE, FormatOptions.json()) .setCreateDisposition(JobInfo.CreateDisposition.CREATE_IF_NEEDED) .setSchema(TABLE_SCHEMA) .build(); @@ -294,6 +302,7 @@ public static void beforeClass() throws InterruptedException, TimeoutException { public static void afterClass() throws ExecutionException, InterruptedException { if (bigquery != null) { RemoteBigQueryHelper.forceDelete(bigquery, DATASET); + RemoteBigQueryHelper.forceDelete(bigquery, MODEL_DATASET); } if (storage != null) { boolean wasDeleted = RemoteStorageHelper.forceDelete(storage, BUCKET, 10, TimeUnit.SECONDS); @@ -498,10 +507,10 @@ public void testCreateExternalTable() throws InterruptedException { assertEquals(TABLE_SCHEMA, remoteTable.getDefinition().getSchema()); QueryJobConfiguration config = QueryJobConfiguration.newBuilder( - "SELECT TimestampField, StringField, IntegerArrayField, BooleanField FROM " - + DATASET - + "." - + tableName) + "SELECT TimestampField, StringField, IntegerArrayField, BooleanField FROM " + + DATASET + + "." + + tableName) .setDefaultDataset(DatasetId.of(DATASET)) .setUseLegacySql(true) .build(); @@ -539,9 +548,9 @@ public void testCreateViewTable() throws InterruptedException { TableId tableId = TableId.of(DATASET, tableName); ViewDefinition viewDefinition = ViewDefinition.newBuilder( - String.format( - "SELECT TimestampField, StringField, BooleanField FROM %s.%s", - DATASET, TABLE_ID.getTable())) + String.format( + "SELECT TimestampField, StringField, BooleanField FROM %s.%s", + DATASET, TABLE_ID.getTable())) .setUseLegacySql(true) .build(); TableInfo tableInfo = TableInfo.of(tableId, viewDefinition); @@ -631,9 +640,9 @@ public void testListTablesWithPartitioning() { if (standardTableDefinition.getTimePartitioning() != null && standardTableDefinition.getTimePartitioning().getType().equals(Type.DAY) && standardTableDefinition - .getTimePartitioning() - .getExpirationMs() - .equals(EXPIRATION_MS)) { + .getTimePartitioning() + .getExpirationMs() + .equals(EXPIRATION_MS)) { found = true; } } @@ -716,9 +725,9 @@ public void testUpdateTimePartitioning() { Table table = bigquery.create(TableInfo.of(tableId, tableDefinition)); assertThat(table.getDefinition()).isInstanceOf(StandardTableDefinition.class); assertThat( - ((StandardTableDefinition) table.getDefinition()) - .getTimePartitioning() - .getExpirationMs()) + ((StandardTableDefinition) table.getDefinition()) + .getTimePartitioning() + .getExpirationMs()) .isNull(); table = @@ -732,9 +741,9 @@ public void testUpdateTimePartitioning() { .build() .update(BigQuery.TableOption.fields(BigQuery.TableField.TIME_PARTITIONING)); assertThat( - ((StandardTableDefinition) table.getDefinition()) - .getTimePartitioning() - .getExpirationMs()) + ((StandardTableDefinition) table.getDefinition()) + .getTimePartitioning() + .getExpirationMs()) .isEqualTo(42L); table = @@ -748,9 +757,9 @@ public void testUpdateTimePartitioning() { .build() .update(BigQuery.TableOption.fields(BigQuery.TableField.TIME_PARTITIONING)); assertThat( - ((StandardTableDefinition) table.getDefinition()) - .getTimePartitioning() - .getExpirationMs()) + ((StandardTableDefinition) table.getDefinition()) + .getTimePartitioning() + .getExpirationMs()) .isNull(); table.delete(); @@ -1042,6 +1051,56 @@ public void testListAllTableData() { assertEquals(2, rowCount); } + @Test + public void testModelLifecycle() throws InterruptedException { + + String modelName = RemoteBigQueryHelper.generateModelName(); + + // Create a model using SQL. + String sql = "CREATE MODEL `" + MODEL_DATASET + "." + modelName + "`" + + "OPTIONS ( " + + "model_type='linear_reg', " + + "max_iteration=1, " + + "learn_rate=0.4, " + + "learn_rate_strategy='constant' " + + ") AS ( " + + " SELECT 'a' AS f1, 2.0 AS label " + + "UNION ALL " + + "SELECT 'b' AS f1, 3.8 AS label " + + ")"; + + QueryJobConfiguration config = + QueryJobConfiguration.newBuilder(sql).build(); + Job job = bigquery.create(JobInfo.of(JobId.of(), config)); + job.waitFor(); + assertNull(job.getStatus().getError()); + + // Model is created. Fetch. + ModelId modelId = ModelId.of(MODEL_DATASET, modelName); + Model model = bigquery.getModel(modelId); + assertNotNull(model); + assertEquals(model.getModelType(), "LINEAR_REGRESSION"); + + // Mutate metadata. + ModelInfo info = model.toBuilder().setDescription("TEST").build(); + Model afterUpdate = bigquery.update(info); + assertEquals(afterUpdate.getDescription(), "TEST"); + + // Ensure model is present in listModels. + Page models = bigquery.listModels(MODEL_DATASET); + Boolean found = false; + for (Model m : models.getValues()) { + if (m.getModelId().getModel().equals(modelName)) { + found = true; + break; + } + } + assertTrue(found); + + // Delete the model. + assertTrue(bigquery.delete(modelId)); + } + @Test public void testQuery() throws InterruptedException { String query = "SELECT TimestampField, StringField, BooleanField FROM " + TABLE_ID.getTable(); @@ -1089,7 +1148,7 @@ public void testPositionalQueryParameters() throws InterruptedException { QueryParameterValue timestampParameter = QueryParameterValue.timestamp("2014-01-01 07:00:00.000000+00:00"); QueryParameterValue intArrayParameter = - QueryParameterValue.array(new Integer[] {3, 4}, Integer.class); + QueryParameterValue.array(new Integer[]{3, 4}, Integer.class); QueryParameterValue int64Parameter = QueryParameterValue.int64(5); QueryParameterValue float64Parameter = QueryParameterValue.float64(0.5); QueryParameterValue numericParameter = @@ -1119,7 +1178,7 @@ public void testNamedQueryParameters() throws InterruptedException { + " AND IntegerField IN UNNEST(@integerList)"; QueryParameterValue stringParameter = QueryParameterValue.string("stringValue"); QueryParameterValue intArrayParameter = - QueryParameterValue.array(new Integer[] {3, 4}, Integer.class); + QueryParameterValue.array(new Integer[]{3, 4}, Integer.class); QueryJobConfiguration config = QueryJobConfiguration.newBuilder(query) .setDefaultDataset(DatasetId.of(DATASET)) @@ -1135,7 +1194,7 @@ public void testNamedQueryParameters() throws InterruptedException { @Test public void testBytesParameter() throws Exception { String query = "SELECT BYTE_LENGTH(@p) AS length"; - QueryParameterValue bytesParameter = QueryParameterValue.bytes(new byte[] {1, 3}); + QueryParameterValue bytesParameter = QueryParameterValue.bytes(new byte[]{1, 3}); QueryJobConfiguration config = QueryJobConfiguration.newBuilder(query) .setDefaultDataset(DatasetId.of(DATASET)) @@ -1522,11 +1581,11 @@ public void testLocation() throws Exception { // Test query { assertThat( - bigquery - .query( - QueryJobConfiguration.of(query), - JobId.newBuilder().setLocation(location).build()) - .iterateAll()) + bigquery + .query( + QueryJobConfiguration.of(query), + JobId.newBuilder().setLocation(location).build()) + .iterateAll()) .isEmpty(); try { From 506d44c6fb331a9949fe52a2b3dfbfe8838add05 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Wed, 24 Apr 2019 16:57:47 -0700 Subject: [PATCH 06/13] more tests and comments --- .../com/google/cloud/bigquery/BigQuery.java | 18 +- .../google/cloud/bigquery/BigQueryImpl.java | 13 +- .../java/com/google/cloud/bigquery/Model.java | 284 +++++----- .../com/google/cloud/bigquery/ModelId.java | 154 +++--- .../com/google/cloud/bigquery/ModelInfo.java | 518 ++++++++++-------- .../bigquery/spi/v2/HttpBigQueryRpc.java | 7 +- .../cloud/bigquery/BigQueryImplTest.java | 46 ++ .../google/cloud/bigquery/ModelIdTest.java | 3 +- .../google/cloud/bigquery/ModelInfoTest.java | 1 - .../com/google/cloud/bigquery/ModelTest.java | 196 +++++++ .../cloud/bigquery/it/ITBigQueryTest.java | 109 ++-- 11 files changed, 853 insertions(+), 496 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java index 9813255b1e7b..097862694c8e 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java @@ -136,8 +136,7 @@ enum ModelField implements FieldSelector { TYPE("modelType"), VIEW("view"); - static final List REQUIRED_FIELDS = - ImmutableList.of(MODEL_REFERENCE); + static final List REQUIRED_FIELDS = ImmutableList.of(MODEL_REFERENCE); private final String selector; @@ -940,6 +939,13 @@ public int hashCode() { */ Table getTable(TableId tableId, TableOption... options); + /** + * Returns the requested model or {@code null} if not found. + * + * @throws BigQueryException upon failure + */ + Model getModel(String datasetId, String modelId, ModelOption... options); + /** * Returns the requested model or {@code null} if not found. * @@ -999,14 +1005,10 @@ public int hashCode() { */ Page
listTables(DatasetId datasetId, TableListOption... options); - /** - * Lists the models in the dataset. - */ + /** Lists the models in the dataset. */ Page listModels(String datasetId, ModelListOption... options); - /** - * Lists the models in the dataset. - */ + /** Lists the models in the dataset. */ Page listModels(DatasetId datasetId, ModelListOption... options); /** diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java index ef8b4763a53d..3694cf559a94 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java @@ -434,9 +434,9 @@ public Boolean call() { public boolean delete(ModelId modelId) { final ModelId completeModelId = modelId.setProjectId( - Strings.isNullOrEmpty(modelId.getProject()) - ? getOptions().getProjectId() - : modelId.getProject()); + Strings.isNullOrEmpty(modelId.getProject()) + ? getOptions().getProjectId() + : modelId.getProject()); try { return runWithRetries( new Callable() { @@ -574,6 +574,11 @@ public com.google.api.services.bigquery.model.Table call() { } } + @Override + public Model getModel(String datasetId, String modelId, ModelOption... options) { + return getModel(ModelId.of(datasetId, modelId), options); + } + @Override public Model getModel(ModelId modelId, ModelOption... options) { final ModelId completeModelId = @@ -699,7 +704,7 @@ private static Page listModels( Tuple>>() { @Override public Tuple> - call() { + call() { return serviceOptions .getBigQueryRpcV2() .listModels(datasetId.getProject(), datasetId.getDataset(), optionsMap); diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java index 368648993bdd..506e222b50a6 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java @@ -16,10 +16,8 @@ package com.google.cloud.bigquery; - import static com.google.common.base.Preconditions.checkNotNull; -import com.google.api.services.bigquery.model.ModelDefinition.ModelOptions; import com.google.cloud.bigquery.BigQuery.ModelOption; import java.io.IOException; import java.io.ObjectInputStream; @@ -29,155 +27,173 @@ /** * A Google BigQuery ML Model. * - *

Objects of this class are immutable. Operations that modify the table like {@link #update} - * return a new object. To get a {@code Model} object with the most recent information use {@link + *

Objects of this class are immutable. Operations that modify the table like {@link #update} + * return a new object. To get a {@code Model} object with the most recent information use {@link * #reload}. - * */ public class Model extends ModelInfo { - private final BigQueryOptions options; - private transient BigQuery bigquery; - - public static class Builder extends ModelInfo.Builder { - - private final BigQuery bigquery; - private final ModelInfo.BuilderImpl infoBuilder; - - Builder(BigQuery bigquery, ModelId modelId) { - this.bigquery = bigquery; - this.infoBuilder = new ModelInfo.BuilderImpl(); - } - - Builder(Model model) { - this.bigquery = model.bigquery; - this.infoBuilder = new ModelInfo.BuilderImpl(model); - } - - @Override - Builder setCreationTime(Long creationTime) { - infoBuilder.setCreationTime(creationTime); - return this; - } - - @Override - public Builder setDescription(String description) { - infoBuilder.setDescription(description); - return this; - } - - @Override - Builder setModelType(String modelType) { - infoBuilder.setModelType(modelType); - return this; - } - - @Override - Builder setEtag(String etag) { - infoBuilder.setEtag(etag); - return this; - } - - @Override - public Builder setExpirationTime(Long expirationTime) { - infoBuilder.setExpirationTime(expirationTime); - return this; - } - - @Override - public Builder setFriendlyName(String friendlyName) { - infoBuilder.setFriendlyName(friendlyName); - return this; - } - - @Override - Builder setLastModifiedTime(Long lastModifiedTime) { - infoBuilder.setLastModifiedTime(lastModifiedTime); - return this; - } - - @Override - public Builder setModelId(ModelId modelId) { - infoBuilder.setModelId(modelId); - return this; - } - - @Override - public Builder setLabels(Map labels) { - infoBuilder.setLabels(labels); - return this; - } - - public Model build() { return new Model(bigquery, infoBuilder); } + private final BigQueryOptions options; + private transient BigQuery bigquery; + + public static class Builder extends ModelInfo.Builder { + + private final BigQuery bigquery; + private final ModelInfo.BuilderImpl infoBuilder; + + Builder(BigQuery bigquery, ModelId modelId) { + this.bigquery = bigquery; + this.infoBuilder = new ModelInfo.BuilderImpl(); + this.infoBuilder.setModelId(modelId); + } + + Builder(Model model) { + this.bigquery = model.bigquery; + this.infoBuilder = new ModelInfo.BuilderImpl(model); + } + + @Override + Builder setCreationTime(Long creationTime) { + infoBuilder.setCreationTime(creationTime); + return this; + } + + @Override + public Builder setDescription(String description) { + infoBuilder.setDescription(description); + return this; + } + + @Override + Builder setModelType(String modelType) { + infoBuilder.setModelType(modelType); + return this; } - Model(BigQuery bigquery, ModelInfo.BuilderImpl infoBuilder) { - super(infoBuilder); - this.bigquery = checkNotNull(bigquery); - this.options = bigquery.getOptions(); + @Override + Builder setEtag(String etag) { + infoBuilder.setEtag(etag); + return this; } - /** Check if this model exists. - * - * @return {@code true} if this table exists, {@code false} otherwise - * @throws BigQueryException upon failure - */ - public boolean exists() { return bigquery.getModel(getModelId(), ModelOption.fields()) != null; } - - /** - * Fetches current model's later information. Returns {@code null} if the model does not exist. - * - * @param options model options - * @return a {@code Model} object with latest information or {@code null} if not found - * @throws BigQueryException upon failure - */ - public Model reload(ModelOption... options) { return bigquery.getModel(getModelId(), options); } - - /** - * Updates the model's information with this model's information. Dataset and model identifiers - * cannot be updates. A new {@code Model} object is returned. - * - * @param options dataset options - * @return a {@code Model} object with updated information - * @throws BigQueryException upon failure - */ - public Model update(ModelOption... options) { return bigquery.update(this, options); } - - /** - * Deletes this model. - * - * @return {@code true} if model was deleted, {@code false} if it was not found - * @throws BigQueryException upon failure - */ - public boolean delete() { return bigquery.delete(getModelId()); } - - /** Return's the model's {@code BigQuery} object used to issuie requests. **/ - public BigQuery getBigQuery() { return bigquery; } + @Override + public Builder setExpirationTime(Long expirationTime) { + infoBuilder.setExpirationTime(expirationTime); + return this; + } @Override - public Builder toBuilder() { return new Builder(this); } + public Builder setFriendlyName(String friendlyName) { + infoBuilder.setFriendlyName(friendlyName); + return this; + } @Override - public final boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj == null || !obj.getClass().equals(Model.class)) { - return false; - } - Model other = (Model) obj; - return Objects.equals(toPb(), other.toPb()) && Objects.equals(options, other.options); + Builder setLastModifiedTime(Long lastModifiedTime) { + infoBuilder.setLastModifiedTime(lastModifiedTime); + return this; } @Override - public final int hashCode() { return Objects.hash(super.hashCode(), options); } + public Builder setModelId(ModelId modelId) { + infoBuilder.setModelId(modelId); + return this; + } - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - this.bigquery = options.getService(); + @Override + public Builder setLabels(Map labels) { + infoBuilder.setLabels(labels); + return this; } - static Model fromPb(BigQuery bigquery, com.google.api.services.bigquery.model.Model modelPb) { - return new Model(bigquery, new ModelInfo.BuilderImpl(modelPb)); + public Model build() { + return new Model(bigquery, infoBuilder); + } + } + + Model(BigQuery bigquery, ModelInfo.BuilderImpl infoBuilder) { + super(infoBuilder); + this.bigquery = checkNotNull(bigquery); + this.options = bigquery.getOptions(); + } + + /** + * Check if this model exists. + * + * @return {@code true} if this table exists, {@code false} otherwise + * @throws BigQueryException upon failure + */ + public boolean exists() { + return bigquery.getModel(getModelId(), ModelOption.fields()) != null; + } + + /** + * Fetches current model's state from the service. Returns {@code null} if the model does not exist. + * A new {@code Model} is returned. + * + * @param options model options + * @return a {@code Model} object with latest information or {@code null} if not found + * @throws BigQueryException upon failure + */ + public Model reload(ModelOption... options) { + return bigquery.getModel(getModelId(), options); + } + + /** + * Updates the model's information with this model's information. Dataset and model identifiers + * cannot be updated. A new {@code Model} object is returned. + * + * @param options dataset options + * @return a {@code Model} object with updated information + * @throws BigQueryException upon failure + */ + public Model update(ModelOption... options) { + return bigquery.update(this, options); + } + + /** + * Deletes this model. + * + * @return {@code true} if model was deleted, {@code false} if it was not found + * @throws BigQueryException upon failure + */ + public boolean delete() { + return bigquery.delete(getModelId()); + } + + /** Return's the model's {@code BigQuery} object used to issue requests. * */ + public BigQuery getBigQuery() { + return bigquery; + } + + @Override + public Builder toBuilder() { + return new Builder(this); + } + + @Override + public final boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || !obj.getClass().equals(Model.class)) { + return false; } + Model other = (Model) obj; + return Objects.equals(toPb(), other.toPb()) && Objects.equals(options, other.options); + } + + @Override + public final int hashCode() { + return Objects.hash(super.hashCode(), options); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + this.bigquery = options.getService(); + } + + static Model fromPb(BigQuery bigquery, com.google.api.services.bigquery.model.Model modelPb) { + return new Model(bigquery, new ModelInfo.BuilderImpl(modelPb)); + } } diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java index 1c32b6a26ba3..32d74fd36b7f 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelId.java @@ -16,85 +16,93 @@ package com.google.cloud.bigquery; -import java.io.Serializable; -import java.util.Objects; - import static com.google.common.base.Preconditions.checkNotNull; import com.google.api.services.bigquery.model.ModelReference; +import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Strings; -import com.google.common.base.Function; +import java.io.Serializable; +import java.util.Objects; public final class ModelId implements Serializable { - static final Function FROM_PB_FUNCTION = - new Function() { - @Override - public ModelId apply(ModelReference pb) { - return ModelId.fromPb(pb); - } - }; - static final Function TO_PB_FUNCTION = - new Function() { - @Override - public ModelReference apply(ModelId modelId) { - return modelId.toPb(); - } - }; - - private final String project; - private final String dataset; - private final String model; - - /** Return corresponding project ID for this model. **/ - public String getProject() { return project; } - - /** Return corresponding dataset ID for this model. **/ - public String getDataset() { return dataset; } - - /** Return corresponding model ID for this model. **/ - public String getModel() { return model; } - - private ModelId(String project, String dataset, String model) { - this.project = project; - this.dataset = dataset; - this.model = model; - } - - /** Creates a model identity given project, dataset, and model identifiers. **/ - public static ModelId of(String project, String dataset, String model) { - return new ModelId(checkNotNull(project), checkNotNull(dataset), checkNotNull(model)); - } - - /** Creates a model identity given dataset and model identifiers. **/ - public static ModelId of(String dataset, String model) { - return new ModelId(null, checkNotNull(dataset), checkNotNull(model)); - } - - @Override public boolean equals(Object obj) { - return obj == this || obj instanceof ModelId && Objects.equals(toPb(), ((ModelId) obj).toPb()); - } - - @Override - public int hashCode() { - return Objects.hash(project, dataset, model); - } - - @Override - public String toString() { - return toPb().toString(); - } - - ModelId setProjectId(String projectId) { - Preconditions.checkArgument( - !Strings.isNullOrEmpty(projectId), "Provided projectId is null or empty"); - return ModelId.of(projectId, getDataset(), getModel()); - } - - ModelReference toPb() { return new ModelReference().setProjectId(project).setDatasetId(dataset).setModelId(model); } - - static ModelId fromPb(ModelReference modelRef) { - return new ModelId(modelRef.getProjectId(), modelRef.getDatasetId(), modelRef.getModelId()); - } + static final Function FROM_PB_FUNCTION = + new Function() { + @Override + public ModelId apply(ModelReference pb) { + return ModelId.fromPb(pb); + } + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public ModelReference apply(ModelId modelId) { + return modelId.toPb(); + } + }; + + private final String project; + private final String dataset; + private final String model; + + /** Return corresponding project ID for this model. * */ + public String getProject() { + return project; + } + + /** Return corresponding dataset ID for this model. * */ + public String getDataset() { + return dataset; + } + + /** Return corresponding model ID for this model. * */ + public String getModel() { + return model; + } + + private ModelId(String project, String dataset, String model) { + this.project = project; + this.dataset = dataset; + this.model = model; + } + + /** Creates a model identity given project, dataset, and model identifiers. * */ + public static ModelId of(String project, String dataset, String model) { + return new ModelId(checkNotNull(project), checkNotNull(dataset), checkNotNull(model)); + } + + /** Creates a model identity given dataset and model identifiers. * */ + public static ModelId of(String dataset, String model) { + return new ModelId(null, checkNotNull(dataset), checkNotNull(model)); + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj instanceof ModelId && Objects.equals(toPb(), ((ModelId) obj).toPb()); + } + + @Override + public int hashCode() { + return Objects.hash(project, dataset, model); + } + + @Override + public String toString() { + return toPb().toString(); + } + + ModelId setProjectId(String projectId) { + Preconditions.checkArgument( + !Strings.isNullOrEmpty(projectId), "Provided projectId is null or empty"); + return ModelId.of(projectId, getDataset(), getModel()); + } + + ModelReference toPb() { + return new ModelReference().setProjectId(project).setDatasetId(dataset).setModelId(model); + } + + static ModelId fromPb(ModelReference modelRef) { + return new ModelId(modelRef.getProjectId(), modelRef.getDatasetId(), modelRef.getModelId()); + } } diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java index c009d30283ab..96a0ed857cf7 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java @@ -16,255 +16,339 @@ package com.google.cloud.bigquery; -import com.google.common.base.Strings; -import java.io.Serializable; -import java.util.Map; -import java.util.Objects; +import static com.google.common.base.Preconditions.checkNotNull; import com.google.api.services.bigquery.model.Model; - import com.google.common.base.Function; import com.google.common.base.MoreObjects; +import com.google.common.base.Strings; +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; -import static com.google.common.base.Preconditions.checkNotNull; - - +/** + * Google BigQuery ML model information. Models are not create directly via the API, but by issuing + * a CREATE MODEL query. + * + * @see CREATE + * MODEL statement + */ public class ModelInfo implements Serializable { - static final Function FROM_PB_FUNCTION = - new Function() { - @Override - public ModelInfo apply(Model pb) { - return ModelInfo.fromPb(pb); - } - }; - static final Function TO_PB_FUNCTION = - new Function() { - @Override - public Model apply(ModelInfo ModelInfo) { - return ModelInfo.toPb(); - } - }; - - private static final long serialVersionUID = 609769793337719407L; - - - private final String etag; - private final ModelId modelId; - private final String description; - private final String modelType; - private final String friendlyName; - private final Long creationTime; - private final Long lastModifiedTime; - private final Long expirationTime; - private final Labels labels; - - - /** A builder for {@code ModelInfo} objects. **/ - public abstract static class Builder { - - public abstract Builder setDescription(String description); - - public abstract Builder setFriendlyName(String friendlyName); - - public abstract Builder setExpirationTime(Long expirationTime); - - public abstract Builder setLabels(Map labels); - - public abstract Builder setModelId(ModelId modelId); - - abstract Builder setEtag(String etag); - abstract Builder setModelType(String modelType); - abstract Builder setCreationTime(Long creation); - abstract Builder setLastModifiedTime(Long lastModifiedTime); - - public abstract ModelInfo build(); - } - - static class BuilderImpl extends Builder { - private String etag; - private ModelId modelId; - private String description; - private String modelType; - private String friendlyName; - private Long creationTime; - private Long lastModifiedTime; - private Long expirationTime; - private Labels labels = Labels.ZERO; - - BuilderImpl() {} - - BuilderImpl(ModelInfo modelInfo) { - this.etag = modelInfo.etag; - this.modelId = modelInfo.modelId; - this.description = modelInfo.description; - this.friendlyName = modelInfo.friendlyName; - this.modelType = modelInfo.modelType; - this.creationTime = modelInfo.creationTime; - this.lastModifiedTime = modelInfo.lastModifiedTime; - this.expirationTime = modelInfo.expirationTime; - } - - BuilderImpl(Model modelPb) { - this.modelId = ModelId.fromPb(modelPb.getModelReference()); - if (modelPb.getLastModifiedTime() != null) { - this.setLastModifiedTime(modelPb.getLastModifiedTime().longValue()); - } - this.etag = modelPb.getEtag(); - this.description = modelPb.getDescription(); - this.friendlyName = modelPb.getFriendlyName(); - this.modelType = modelPb.getModelType(); - this.creationTime = modelPb.getCreationTime(); - this.lastModifiedTime = modelPb.getLastModifiedTime(); - this.expirationTime = modelPb.getExpirationTime(); - this.labels = Labels.fromPb(modelPb.getLabels()); - } - - @Override - Builder setEtag(String etag) { - this.etag = etag; - return this; - } - + static final Function FROM_PB_FUNCTION = + new Function() { @Override - public Builder setDescription(String description) { - this.description = description; - return this; + public ModelInfo apply(Model pb) { + return ModelInfo.fromPb(pb); } - - @Override - public Builder setFriendlyName(String friendlyName) { - this.friendlyName = friendlyName; - return this; - } - + }; + static final Function TO_PB_FUNCTION = + new Function() { @Override - Builder setModelType(String modelType) { - this.modelType = modelType; - return this; + public Model apply(ModelInfo ModelInfo) { + return ModelInfo.toPb(); } - - @Override - Builder setCreationTime(Long creationTime) { - this.creationTime = creationTime; - return this; - } - - @Override - Builder setLastModifiedTime(Long lastModifiedTime) { - this.lastModifiedTime = lastModifiedTime; - return this; - } - - @Override - public Builder setExpirationTime(Long expirationTime) { - this.expirationTime = expirationTime; - return this; - } - - @Override - public Builder setModelId(ModelId modelId) { - this.modelId = modelId; - return this; - } - - @Override - public Builder setLabels(Map labels) { - this.labels = Labels.fromUser(labels); - return this; - } - - @Override - public ModelInfo build() { return new ModelInfo(this); } + }; + + private static final long serialVersionUID = 609769793337719407L; + + private final String etag; + private final ModelId modelId; + private final String description; + private final String modelType; + private final String friendlyName; + private final Long creationTime; + private final Long lastModifiedTime; + private final Long expirationTime; + private final Labels labels; + + /** + * A builder for {@code ModelInfo} objects. + */ + public abstract static class Builder { + + /** + * Sets the user description for this model. + **/ + public abstract Builder setDescription(String description); + + /** + * Sets the user-friendly name for this model. + */ + public abstract Builder setFriendlyName(String friendlyName); + + /** + * Set the time when this model expires, in milliseconds since the epoch. If not present, the + * model persists indefinitely. Expired models will be deleted. + */ + public abstract Builder setExpirationTime(Long expirationTime); + + /** + * Set the labels applied to this model. + * + *

When used with {@link BigQuery#update(ModelInfo, ModelOption...)}, setting {@code labels} + * to {@code null} removes all labels; otherwise all keys that are mapped to {@code null} values + * are removed and other keys are updated to their respective values. + */ + public abstract Builder setLabels(Map labels); + + public abstract Builder setModelId(ModelId modelId); + + abstract Builder setEtag(String etag); + + abstract Builder setModelType(String modelType); + + abstract Builder setCreationTime(Long creation); + + abstract Builder setLastModifiedTime(Long lastModifiedTime); + + /** + * Creates a {@code ModelInfo} object. + */ + public abstract ModelInfo build(); + } + + static class BuilderImpl extends Builder { + + private String etag; + private ModelId modelId; + private String description; + private String modelType; + private String friendlyName; + private Long creationTime; + private Long lastModifiedTime; + private Long expirationTime; + private Labels labels = Labels.ZERO; + + BuilderImpl() { } - ModelInfo(BuilderImpl builder) { - this.modelId = checkNotNull(builder.modelId); - this.etag = builder.etag; - this.modelType = builder.modelType; - this.description = builder.description; - this.friendlyName = builder.friendlyName; - this.creationTime = builder.creationTime; - this.lastModifiedTime = builder.lastModifiedTime; - this.expirationTime = builder.expirationTime; - this.labels = builder.labels; + BuilderImpl(ModelInfo modelInfo) { + this.etag = modelInfo.etag; + this.modelId = modelInfo.modelId; + this.description = modelInfo.description; + this.friendlyName = modelInfo.friendlyName; + this.modelType = modelInfo.modelType; + this.creationTime = modelInfo.creationTime; + this.lastModifiedTime = modelInfo.lastModifiedTime; + this.expirationTime = modelInfo.expirationTime; } - public String getEtag() { return etag; } - - public ModelId getModelId() { return modelId; } - - public String getModelType() { return modelType; } - - public String getDescription() { return description; } - - public String getFriendlyName() { return friendlyName; } - - public Long getCreationTime() { return creationTime; } - - public Long getLastModifiedTime() { return lastModifiedTime; } - - public Long getExpirationTime() { return expirationTime; } - - public Map getLabels() { return labels.userMap(); } + BuilderImpl(Model modelPb) { + this.modelId = ModelId.fromPb(modelPb.getModelReference()); + if (modelPb.getLastModifiedTime() != null) { + this.setLastModifiedTime(modelPb.getLastModifiedTime().longValue()); + } + this.etag = modelPb.getEtag(); + this.description = modelPb.getDescription(); + this.friendlyName = modelPb.getFriendlyName(); + this.modelType = modelPb.getModelType(); + this.creationTime = modelPb.getCreationTime(); + this.lastModifiedTime = modelPb.getLastModifiedTime(); + this.expirationTime = modelPb.getExpirationTime(); + this.labels = Labels.fromPb(modelPb.getLabels()); + } - public Builder toBuilder() { return new BuilderImpl(this); } + @Override + Builder setEtag(String etag) { + this.etag = etag; + return this; + } @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("modelId", modelId) - .add("etag", etag) - .add("modelType", modelType) - .add("description", description) - .add("friendlyName", friendlyName) - .add("creationTime", creationTime) - .add("lastModifiedTime", lastModifiedTime) - .add("expirationTime", expirationTime) - .add("labels", labels) - .toString(); + public Builder setDescription(String description) { + this.description = description; + return this; } @Override - public int hashCode() { return Objects.hash(modelId); } + public Builder setFriendlyName(String friendlyName) { + this.friendlyName = friendlyName; + return this; + } @Override - public boolean equals(Object obj) { - return obj == this - || obj != null - && obj.getClass().equals(ModelInfo.class) - && Objects.equals(toPb(), ((ModelInfo) obj).toPb()); + Builder setModelType(String modelType) { + this.modelType = modelType; + return this; } - public static Builder newBuilder(ModelId modelId) { - return new BuilderImpl().setModelId(modelId); + @Override + Builder setCreationTime(Long creationTime) { + this.creationTime = creationTime; + return this; } - public static ModelInfo of(ModelId modelId) { - return newBuilder(modelId).build(); + @Override + Builder setLastModifiedTime(Long lastModifiedTime) { + this.lastModifiedTime = lastModifiedTime; + return this; } - ModelInfo setProjectId(String projectId) { - if (Strings.isNullOrEmpty(getModelId().getProject())) { - return toBuilder().setModelId(getModelId().setProjectId(projectId)).build(); - } - return this; + @Override + public Builder setExpirationTime(Long expirationTime) { + this.expirationTime = expirationTime; + return this; } - Model toPb() { - Model modelPb = new Model(); - modelPb.setModelReference(modelId.toPb()); - modelPb.setEtag(etag); - modelPb.setModelType(modelType); - modelPb.setDescription(description); - modelPb.setFriendlyName(friendlyName); - modelPb.setCreationTime(creationTime); - modelPb.setLastModifiedTime(lastModifiedTime); - modelPb.setExpirationTime(expirationTime); - modelPb.setLabels(labels.toPb()); - return modelPb; + @Override + public Builder setModelId(ModelId modelId) { + this.modelId = modelId; + return this; } - static ModelInfo fromPb(Model modelPb) { return new BuilderImpl(modelPb).build(); } + @Override + public Builder setLabels(Map labels) { + this.labels = Labels.fromUser(labels); + return this; + } + @Override + public ModelInfo build() { + return new ModelInfo(this); + } + } + + ModelInfo(BuilderImpl builder) { + this.modelId = checkNotNull(builder.modelId); + this.etag = builder.etag; + this.modelType = builder.modelType; + this.description = builder.description; + this.friendlyName = builder.friendlyName; + this.creationTime = builder.creationTime; + this.lastModifiedTime = builder.lastModifiedTime; + this.expirationTime = builder.expirationTime; + this.labels = builder.labels; + } + + /** + * Returns the hash of the model resource. + */ + public String getEtag() { + return etag; + } + + /** + * Returns the model identity. + */ + public ModelId getModelId() { + return modelId; + } + + /** + * Returns the type of the ML model. + */ + public String getModelType() { + return modelType; + } + + /** + * Returns the user description of the model. + */ + public String getDescription() { + return description; + } + + /** + * Returns the user-friendly name for the model. + */ + public String getFriendlyName() { + return friendlyName; + } + + /** + * Returns the time when this model was created, in milliseconds since the epoch. + */ + public Long getCreationTime() { + return creationTime; + } + + /** + * Returns the time when this table was last modified, in milliseconds since the epoch. + */ + public Long getLastModifiedTime() { + return lastModifiedTime; + } + + /** + * Returns this this model expires, in milliseconds since the epoch. If not present, the model + * will persist indefinitely. Expired models will be deleted. + */ + public Long getExpirationTime() { + return expirationTime; + } + + /** + * Returns a map for labels applied to the model. + */ + public Map getLabels() { + return labels.userMap(); + } + + public Builder toBuilder() { + return new BuilderImpl(this); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("modelId", modelId) + .add("etag", etag) + .add("modelType", modelType) + .add("description", description) + .add("friendlyName", friendlyName) + .add("creationTime", creationTime) + .add("lastModifiedTime", lastModifiedTime) + .add("expirationTime", expirationTime) + .add("labels", labels) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(modelId); + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj != null + && obj.getClass().equals(ModelInfo.class) + && Objects.equals(toPb(), ((ModelInfo) obj).toPb()); + } + + /** Returns a builder for a {@code ModelInfo} object given table identity. */ + public static Builder newBuilder(ModelId modelId) { + return new BuilderImpl().setModelId(modelId); + } + + /** Returns a {@code ModelInfo} object given table identity. */ + public static ModelInfo of(ModelId modelId) { + return newBuilder(modelId).build(); + } + + ModelInfo setProjectId(String projectId) { + if (Strings.isNullOrEmpty(getModelId().getProject())) { + return toBuilder().setModelId(getModelId().setProjectId(projectId)).build(); + } + return this; + } + + Model toPb() { + Model modelPb = new Model(); + modelPb.setModelReference(modelId.toPb()); + modelPb.setEtag(etag); + modelPb.setModelType(modelType); + modelPb.setDescription(description); + modelPb.setFriendlyName(friendlyName); + modelPb.setCreationTime(creationTime); + modelPb.setLastModifiedTime(lastModifiedTime); + modelPb.setExpirationTime(expirationTime); + modelPb.setLabels(labels.toPb()); + return modelPb; + } + + static ModelInfo fromPb(Model modelPb) { + return new BuilderImpl(modelPb).build(); + } } diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java index 638eb9f823d4..4a83eb32fdbc 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java @@ -319,8 +319,8 @@ public Model patch(Model model, Map options) { } @Override - public Model getModel(String projectId, String datasetId, String modelId, - Map options) { + public Model getModel( + String projectId, String datasetId, String modelId, Map options) { try { return bigquery .models() @@ -348,8 +348,7 @@ public Tuple> listModels( .setPageToken(Option.PAGE_TOKEN.getString(options)) .execute(); Iterable models = modelList.getModels(); - return Tuple.of( - modelList.getNextPageToken(), models); + return Tuple.of(modelList.getNextPageToken(), models); } catch (IOException ex) { throw translate(ex); } diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java index 8d589bcb59ab..7da22da48c39 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java @@ -70,6 +70,8 @@ public class BigQueryImplTest { private static final String OTHER_PROJECT = "otherProject"; private static final String DATASET = "dataset"; private static final String TABLE = "table"; + private static final String MODEL = "model"; + private static final String OTHER_MODEL = "otherModel"; private static final String JOB = "job"; private static final String OTHER_TABLE = "otherTable"; private static final String OTHER_DATASET = "otherDataset"; @@ -130,6 +132,15 @@ public class BigQueryImplTest { TableInfo.newBuilder(TABLE_ID, TABLE_DEFINITION_WITH_PARTITIONING) .setCreationTime(TABLE_CREATION_TIME) .build(); + + private static final ModelId MODEL_ID = ModelId.of(DATASET, MODEL); + private static final ModelId OTHER_MODEL_ID = ModelId.of(DATASET, OTHER_MODEL); + private static final ModelId MODEL_ID_WITH_PROJECT = ModelId.of(PROJECT, DATASET, MODEL); + + private static final ModelInfo MODEL_INFO = ModelInfo.of(MODEL_ID); + private static final ModelInfo OTHER_MODEL_INFO = ModelInfo.of(OTHER_MODEL_ID); + private static final ModelInfo MODEL_INFO_WITH_PROJECT = ModelInfo.of(MODEL_ID_WITH_PROJECT); + private static final LoadJobConfiguration LOAD_JOB_CONFIGURATION = LoadJobConfiguration.of(TABLE_ID, "URI"); private static final LoadJobConfiguration LOAD_JOB_CONFIGURATION_WITH_PROJECT = @@ -761,6 +772,16 @@ public void testGetTable() { assertEquals(new Table(bigquery, new TableInfo.BuilderImpl(TABLE_INFO_WITH_PROJECT)), table); } + @Test + public void testGetModel() { + EasyMock.expect(bigqueryRpcMock.getModel(PROJECT, DATASET, MODEL, EMPTY_RPC_OPTIONS)) + .andReturn(MODEL_INFO_WITH_PROJECT.toPb()); + EasyMock.replay(bigqueryRpcMock); + bigquery = options.getService(); + Model model = bigquery.getModel(DATASET, MODEL); + assertEquals(new Model(bigquery, new ModelInfo.BuilderImpl(MODEL_INFO_WITH_PROJECT)), model); + } + @Test public void testListPartition() { EasyMock.expect( @@ -936,6 +957,23 @@ public void testListTablesWithOptions() { assertArrayEquals(tableList.toArray(), Iterables.toArray(page.getValues(), Table.class)); } + @Test + public void testListModels() { + bigquery = options.getService(); + ImmutableList modelList = + ImmutableList.of( + new Model(bigquery, new ModelInfo.BuilderImpl(MODEL_INFO_WITH_PROJECT)), + new Model(bigquery, new ModelInfo.BuilderImpl(OTHER_MODEL_INFO))); + Tuple> result = + Tuple.of(CURSOR, Iterables.transform(modelList, ModelInfo.TO_PB_FUNCTION)); + EasyMock.expect(bigqueryRpcMock.listModels(PROJECT, DATASET, EMPTY_RPC_OPTIONS)) + .andReturn(result); + EasyMock.replay(bigqueryRpcMock); + Page page = bigquery.listModels(DATASET); + assertEquals(CURSOR, page.getNextPageToken()); + assertArrayEquals(modelList.toArray(), Iterables.toArray(page.getValues(), Model.class)); + } + @Test public void testDeleteTable() { EasyMock.expect(bigqueryRpcMock.deleteTable(PROJECT, DATASET, TABLE)).andReturn(true); @@ -973,6 +1011,14 @@ public void testDeleteTableFromTableIdWithoutProject() { assertTrue(bigquery.delete(tableId)); } + @Test + public void testDeleteModel() { + EasyMock.expect(bigqueryRpcMock.deleteModel(PROJECT, DATASET, MODEL)).andReturn(true); + EasyMock.replay(bigqueryRpcMock); + bigquery = options.getService(); + assertTrue(bigquery.delete(DATASET, MODEL)); + } + @Test public void testUpdateTable() { TableInfo updatedTableInfo = diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java index a3adc0207350..266a754c4455 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelIdTest.java @@ -60,5 +60,4 @@ private void compareModelIds(ModelId expected, ModelId value) { assertEquals(expected.getDataset(), value.getDataset()); assertEquals(expected.hashCode(), value.hashCode()); } - -} \ No newline at end of file +} diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java index 70a6fe701b74..c5590b1afb57 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelInfoTest.java @@ -40,7 +40,6 @@ public class ModelInfoTest { .setFriendlyName(FRIENDLY_NAME) .build(); - @Test public void testToBuilder() { compareModelInfo(MODEL_INFO, MODEL_INFO.toBuilder().build()); diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java index 9ff55829b600..e512a6496c82 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java @@ -16,6 +16,202 @@ package com.google.cloud.bigquery; +import static com.google.cloud.bigquery.ModelIdTest.MODEL; +import static com.google.common.truth.Truth.assertThat; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createStrictMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import com.google.api.gax.paging.Page; +import com.google.cloud.PageImpl; +import org.junit.After; +import org.junit.Test; + public class ModelTest { + private BigQuery serviceMockReturnsOptions = createStrictMock(BigQuery.class); + private BigQueryOptions mockOptions = createMock(BigQueryOptions.class); + + + private static final ModelId MODEL_ID = ModelId.of("dataset", "model"); + private static final String ETAG = "etag"; + private static final Long CREATION_TIME = 10L; + private static final Long LAST_MODIFIED_TIME = 20L; + private static final Long EXPIRATION_TIME = 30L; + private static final String DESCRIPTION = "description"; + private static final String FRIENDLY_NAME = "friendlyname"; + + private static final ModelInfo MODEL_INFO = + ModelInfo.newBuilder(MODEL_ID) + .setEtag(ETAG) + .setCreationTime(CREATION_TIME) + .setExpirationTime(EXPIRATION_TIME) + .setLastModifiedTime(LAST_MODIFIED_TIME) + .setDescription(DESCRIPTION) + .setFriendlyName(FRIENDLY_NAME) + .build(); + + private BigQuery bigquery; + private Model expectedModel; + private Model model; + + + private void initializeExpectedModel(int optionsCalls) { + expect(serviceMockReturnsOptions.getOptions()).andReturn(mockOptions).times(optionsCalls); + replay(serviceMockReturnsOptions); + bigquery = createStrictMock(BigQuery.class); + expectedModel = new Model(serviceMockReturnsOptions, new ModelInfo.BuilderImpl(MODEL_INFO)); + } + + private void initializeModel() { + model = new Model(bigquery, new ModelInfo.BuilderImpl(MODEL_INFO)); + } + + @After + public void tearDown() throws Exception { + verify(bigquery, serviceMockReturnsOptions); + } + + + @Test + public void testBuilder() { + initializeExpectedModel(2); + replay(bigquery); + Model builtModel = new Model.Builder(serviceMockReturnsOptions, MODEL_ID) + .setEtag(ETAG) + .setCreationTime(CREATION_TIME) + .setExpirationTime(EXPIRATION_TIME) + .setLastModifiedTime(LAST_MODIFIED_TIME) + .setDescription(DESCRIPTION) + .setFriendlyName(FRIENDLY_NAME) + .build(); + assertEquals(ETAG, builtModel.getEtag()); + assertSame(serviceMockReturnsOptions, builtModel.getBigQuery()); + } + + @Test + public void testToBuilder() { + initializeExpectedModel(2); + replay(bigquery); + compareModelInfo(expectedModel, expectedModel.toBuilder().build()); + } + + @Test + public void testExists_True() throws Exception { + initializeExpectedModel(1); + BigQuery.ModelOption[] expectedOptions = {BigQuery.ModelOption.fields()}; + expect(bigquery.getOptions()).andReturn(mockOptions); + expect(bigquery.getModel(MODEL_INFO.getModelId(), expectedOptions)).andReturn(expectedModel); + replay(bigquery); + initializeModel(); + assertTrue(model.exists()); + } + + @Test + public void testExists_False() throws Exception { + initializeExpectedModel(1); + BigQuery.ModelOption[] expectedOptions = {BigQuery.ModelOption.fields()}; + expect(bigquery.getOptions()).andReturn(mockOptions); + expect(bigquery.getModel(MODEL_INFO.getModelId(), expectedOptions)).andReturn(null); + replay(bigquery); + initializeModel(); + assertFalse(model.exists()); + } + + @Test + public void testReload() throws Exception { + initializeExpectedModel(4); + ModelInfo updatedInfo = MODEL_INFO.toBuilder().setDescription("Description").build(); + Model expectedModel = + new Model(serviceMockReturnsOptions, new ModelInfo.BuilderImpl(updatedInfo)); + expect(bigquery.getOptions()).andReturn(mockOptions); + expect(bigquery.getModel(MODEL_INFO.getModelId())).andReturn(expectedModel); + replay(bigquery); + initializeModel(); + Model updatedModel = model.reload(); + compareModel(expectedModel, updatedModel); + } + + @Test + public void testReloadNull() throws Exception { + initializeExpectedModel(1); + expect(bigquery.getOptions()).andReturn(mockOptions); + expect(bigquery.getModel(MODEL_INFO.getModelId())).andReturn(null); + replay(bigquery); + initializeModel(); + assertNull(model.reload()); + } + + @Test + public void testUpdate() { + initializeExpectedModel(4); + Model expectedUpdatedModel = expectedModel.toBuilder().setDescription("Description").build(); + expect(bigquery.getOptions()).andReturn(mockOptions); + expect(bigquery.update(eq(expectedModel))).andReturn(expectedUpdatedModel); + replay(bigquery); + initializeModel(); + Model actualUpdatedModel = model.update(); + compareModel(expectedUpdatedModel, actualUpdatedModel); + } + + @Test + public void testUpdateWithOptions() { + initializeExpectedModel(4); + Model expectedUpdatedModel = expectedModel.toBuilder().setDescription("Description").build(); + expect(bigquery.getOptions()).andReturn(mockOptions); + expect(bigquery.update(eq(expectedModel), eq(BigQuery.ModelOption.fields()))) + .andReturn(expectedUpdatedModel); + replay(bigquery); + initializeModel(); + Model actualUpdatedModel = model.update(BigQuery.ModelOption.fields()); + compareModel(expectedUpdatedModel, actualUpdatedModel); + } + + @Test + public void testDeleteTrue() { + initializeExpectedModel(1); + expect(bigquery.getOptions()).andReturn(mockOptions); + expect(bigquery.delete(MODEL_INFO.getModelId())).andReturn(true); + replay(bigquery); + initializeModel(); + assertTrue(model.delete()); + } + + @Test + public void testDeleteFalse() { + initializeExpectedModel(1); + expect(bigquery.getOptions()).andReturn(mockOptions); + expect(bigquery.delete(MODEL_INFO.getModelId())).andReturn(false); + replay(bigquery); + initializeModel(); + assertFalse(model.delete()); + } + + + private void compareModel(Model expected, Model value) { + assertEquals(expected, value); + compareModelInfo(expected, value); + assertEquals(expected.getBigQuery().getOptions(), value.getBigQuery().getOptions()); + } + + private void compareModelInfo(ModelInfo expected, ModelInfo value) { + assertEquals(expected, value); + assertEquals(expected.getModelId(), value.getModelId()); + assertEquals(expected.getEtag(), value.getEtag()); + assertEquals(expected.getCreationTime(), value.getCreationTime()); + assertEquals(expected.getLastModifiedTime(), value.getLastModifiedTime()); + assertEquals(expected.getExpirationTime(), value.getExpirationTime()); + assertEquals(expected.getDescription(), value.getDescription()); + assertEquals(expected.getFriendlyName(), value.getFriendlyName()); + assertEquals(expected.getLabels(), value.getLabels()); + assertEquals(expected.hashCode(), value.hashCode()); + } } diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java index aa3e6ce5305c..7dc394add0f7 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java @@ -92,7 +92,6 @@ import java.math.BigDecimal; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.rmi.Remote; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -154,13 +153,13 @@ public class ITBigQueryTest { .build(); private static final Field RECORD_FIELD_SCHEMA = Field.newBuilder( - "RecordField", - LegacySQLTypeName.RECORD, - TIMESTAMP_FIELD_SCHEMA, - STRING_FIELD_SCHEMA, - INTEGER_ARRAY_FIELD_SCHEMA, - BOOLEAN_FIELD_SCHEMA, - BYTES_FIELD_SCHEMA) + "RecordField", + LegacySQLTypeName.RECORD, + TIMESTAMP_FIELD_SCHEMA, + STRING_FIELD_SCHEMA, + INTEGER_ARRAY_FIELD_SCHEMA, + BOOLEAN_FIELD_SCHEMA, + BYTES_FIELD_SCHEMA) .setMode(Field.Mode.REQUIRED) .setDescription("RecordDescription") .build(); @@ -266,8 +265,7 @@ public class ITBigQueryTest { private static BigQuery bigquery; private static Storage storage; - @Rule - public Timeout globalTimeout = Timeout.seconds(300); + @Rule public Timeout globalTimeout = Timeout.seconds(300); @BeforeClass public static void beforeClass() throws InterruptedException, TimeoutException { @@ -285,11 +283,12 @@ public static void beforeClass() throws InterruptedException, TimeoutException { DatasetInfo info = DatasetInfo.newBuilder(DATASET).setDescription(DESCRIPTION).setLabels(LABELS).build(); bigquery.create(info); - DatasetInfo info2 = DatasetInfo.newBuilder(MODEL_DATASET).setDescription("java model lifecycle").build(); + DatasetInfo info2 = + DatasetInfo.newBuilder(MODEL_DATASET).setDescription("java model lifecycle").build(); bigquery.create(info2); LoadJobConfiguration configuration = LoadJobConfiguration.newBuilder( - TABLE_ID, "gs://" + BUCKET + "/" + JSON_LOAD_FILE, FormatOptions.json()) + TABLE_ID, "gs://" + BUCKET + "/" + JSON_LOAD_FILE, FormatOptions.json()) .setCreateDisposition(JobInfo.CreateDisposition.CREATE_IF_NEEDED) .setSchema(TABLE_SCHEMA) .build(); @@ -507,10 +506,10 @@ public void testCreateExternalTable() throws InterruptedException { assertEquals(TABLE_SCHEMA, remoteTable.getDefinition().getSchema()); QueryJobConfiguration config = QueryJobConfiguration.newBuilder( - "SELECT TimestampField, StringField, IntegerArrayField, BooleanField FROM " - + DATASET - + "." - + tableName) + "SELECT TimestampField, StringField, IntegerArrayField, BooleanField FROM " + + DATASET + + "." + + tableName) .setDefaultDataset(DatasetId.of(DATASET)) .setUseLegacySql(true) .build(); @@ -548,9 +547,9 @@ public void testCreateViewTable() throws InterruptedException { TableId tableId = TableId.of(DATASET, tableName); ViewDefinition viewDefinition = ViewDefinition.newBuilder( - String.format( - "SELECT TimestampField, StringField, BooleanField FROM %s.%s", - DATASET, TABLE_ID.getTable())) + String.format( + "SELECT TimestampField, StringField, BooleanField FROM %s.%s", + DATASET, TABLE_ID.getTable())) .setUseLegacySql(true) .build(); TableInfo tableInfo = TableInfo.of(tableId, viewDefinition); @@ -640,9 +639,9 @@ public void testListTablesWithPartitioning() { if (standardTableDefinition.getTimePartitioning() != null && standardTableDefinition.getTimePartitioning().getType().equals(Type.DAY) && standardTableDefinition - .getTimePartitioning() - .getExpirationMs() - .equals(EXPIRATION_MS)) { + .getTimePartitioning() + .getExpirationMs() + .equals(EXPIRATION_MS)) { found = true; } } @@ -725,9 +724,9 @@ public void testUpdateTimePartitioning() { Table table = bigquery.create(TableInfo.of(tableId, tableDefinition)); assertThat(table.getDefinition()).isInstanceOf(StandardTableDefinition.class); assertThat( - ((StandardTableDefinition) table.getDefinition()) - .getTimePartitioning() - .getExpirationMs()) + ((StandardTableDefinition) table.getDefinition()) + .getTimePartitioning() + .getExpirationMs()) .isNull(); table = @@ -741,9 +740,9 @@ public void testUpdateTimePartitioning() { .build() .update(BigQuery.TableOption.fields(BigQuery.TableField.TIME_PARTITIONING)); assertThat( - ((StandardTableDefinition) table.getDefinition()) - .getTimePartitioning() - .getExpirationMs()) + ((StandardTableDefinition) table.getDefinition()) + .getTimePartitioning() + .getExpirationMs()) .isEqualTo(42L); table = @@ -757,9 +756,9 @@ public void testUpdateTimePartitioning() { .build() .update(BigQuery.TableOption.fields(BigQuery.TableField.TIME_PARTITIONING)); assertThat( - ((StandardTableDefinition) table.getDefinition()) - .getTimePartitioning() - .getExpirationMs()) + ((StandardTableDefinition) table.getDefinition()) + .getTimePartitioning() + .getExpirationMs()) .isNull(); table.delete(); @@ -1057,20 +1056,24 @@ public void testModelLifecycle() throws InterruptedException { String modelName = RemoteBigQueryHelper.generateModelName(); // Create a model using SQL. - String sql = "CREATE MODEL `" + MODEL_DATASET + "." + modelName + "`" - + "OPTIONS ( " - + "model_type='linear_reg', " - + "max_iteration=1, " - + "learn_rate=0.4, " - + "learn_rate_strategy='constant' " - + ") AS ( " - + " SELECT 'a' AS f1, 2.0 AS label " - + "UNION ALL " - + "SELECT 'b' AS f1, 3.8 AS label " - + ")"; - - QueryJobConfiguration config = - QueryJobConfiguration.newBuilder(sql).build(); + String sql = + "CREATE MODEL `" + + MODEL_DATASET + + "." + + modelName + + "`" + + "OPTIONS ( " + + "model_type='linear_reg', " + + "max_iteration=1, " + + "learn_rate=0.4, " + + "learn_rate_strategy='constant' " + + ") AS ( " + + " SELECT 'a' AS f1, 2.0 AS label " + + "UNION ALL " + + "SELECT 'b' AS f1, 3.8 AS label " + + ")"; + + QueryJobConfiguration config = QueryJobConfiguration.newBuilder(sql).build(); Job job = bigquery.create(JobInfo.of(JobId.of(), config)); job.waitFor(); assertNull(job.getStatus().getError()); @@ -1148,7 +1151,7 @@ public void testPositionalQueryParameters() throws InterruptedException { QueryParameterValue timestampParameter = QueryParameterValue.timestamp("2014-01-01 07:00:00.000000+00:00"); QueryParameterValue intArrayParameter = - QueryParameterValue.array(new Integer[]{3, 4}, Integer.class); + QueryParameterValue.array(new Integer[] {3, 4}, Integer.class); QueryParameterValue int64Parameter = QueryParameterValue.int64(5); QueryParameterValue float64Parameter = QueryParameterValue.float64(0.5); QueryParameterValue numericParameter = @@ -1178,7 +1181,7 @@ public void testNamedQueryParameters() throws InterruptedException { + " AND IntegerField IN UNNEST(@integerList)"; QueryParameterValue stringParameter = QueryParameterValue.string("stringValue"); QueryParameterValue intArrayParameter = - QueryParameterValue.array(new Integer[]{3, 4}, Integer.class); + QueryParameterValue.array(new Integer[] {3, 4}, Integer.class); QueryJobConfiguration config = QueryJobConfiguration.newBuilder(query) .setDefaultDataset(DatasetId.of(DATASET)) @@ -1194,7 +1197,7 @@ public void testNamedQueryParameters() throws InterruptedException { @Test public void testBytesParameter() throws Exception { String query = "SELECT BYTE_LENGTH(@p) AS length"; - QueryParameterValue bytesParameter = QueryParameterValue.bytes(new byte[]{1, 3}); + QueryParameterValue bytesParameter = QueryParameterValue.bytes(new byte[] {1, 3}); QueryJobConfiguration config = QueryJobConfiguration.newBuilder(query) .setDefaultDataset(DatasetId.of(DATASET)) @@ -1581,11 +1584,11 @@ public void testLocation() throws Exception { // Test query { assertThat( - bigquery - .query( - QueryJobConfiguration.of(query), - JobId.newBuilder().setLocation(location).build()) - .iterateAll()) + bigquery + .query( + QueryJobConfiguration.of(query), + JobId.newBuilder().setLocation(location).build()) + .iterateAll()) .isEmpty(); try { From f100375daa722193384ce563476e3319a96ff7d8 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Thu, 25 Apr 2019 12:21:56 -0700 Subject: [PATCH 07/13] more tests, mark bigquery.delete(string, string, string) deprecated --- .../java/com/google/cloud/bigquery/BigQuery.java | 16 ++++------------ .../google/cloud/bigquery/BigQueryImplTest.java | 2 +- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java index 097862694c8e..a20cfb387459 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java @@ -748,22 +748,14 @@ public int hashCode() { /** * Deletes the requested table. * - *

Example of deleting a table. - * - *

{@code
-   * String datasetName = "my_dataset_name";
-   * String tableName = "my_table_name";
-   * boolean deleted = bigquery.delete(datasetName, tableName);
-   * if (deleted) {
-   *   // the table was deleted
-   * } else {
-   *   // the table was not found
-   * }
-   * }
+ * @deprecated Now that BigQuery datasets contain multiple resource types, this + * invocation is ambiguous. Please use more strongly typed version of {@code #delete}. + * This will continue to target tables. * * @return {@code true} if table was deleted, {@code false} if it was not found * @throws BigQueryException upon failure */ + @Deprecated boolean delete(String datasetId, String tableId); /** diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java index 7da22da48c39..615fce526c08 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java @@ -1016,7 +1016,7 @@ public void testDeleteModel() { EasyMock.expect(bigqueryRpcMock.deleteModel(PROJECT, DATASET, MODEL)).andReturn(true); EasyMock.replay(bigqueryRpcMock); bigquery = options.getService(); - assertTrue(bigquery.delete(DATASET, MODEL)); + assertTrue(bigquery.delete(ModelId.of(DATASET, MODEL))); } @Test From 715a99a5cc2431bb54bcc63d94cb34feccde9c67 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Mon, 29 Apr 2019 11:08:10 -0700 Subject: [PATCH 08/13] typo --- .../src/main/java/com/google/cloud/bigquery/BigQuery.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java index a20cfb387459..936abc4fe4f6 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java @@ -877,7 +877,7 @@ public int hashCode() { * ModelInfo modelInfo = beforeModel.toBuilder() * .setDescription(newDescription) * .build(); - * Model afterModel = bigquery.update(moddelInfo); + * Model afterModel = bigquery.update(modelInfo); * } * *

Example of updating a model by changing its expiration. From 16d3ab8a111486cfd959347d4cc48827df8fb749 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Wed, 8 May 2019 11:06:36 -0700 Subject: [PATCH 09/13] address review comments --- .../java/com/google/cloud/bigquery/BigQuery.java | 1 - .../main/java/com/google/cloud/bigquery/Model.java | 12 ++++++------ .../java/com/google/cloud/bigquery/ModelInfo.java | 2 +- .../google/cloud/bigquery/spi/v2/BigQueryRpc.java | 12 +++++++----- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java index 13ea4b887071..3750161747dd 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java @@ -134,7 +134,6 @@ enum ModelField implements FieldSelector { MODEL_REFERENCE("modelReference"), TIME_PARTITIONING("timePartitioning"), TYPE("modelType"), - VIEW("view"); static final List REQUIRED_FIELDS = ImmutableList.of(MODEL_REFERENCE); diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java index 506e222b50a6..7308232db349 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java @@ -64,12 +64,6 @@ public Builder setDescription(String description) { return this; } - @Override - Builder setModelType(String modelType) { - infoBuilder.setModelType(modelType); - return this; - } - @Override Builder setEtag(String etag) { infoBuilder.setEtag(etag); @@ -100,6 +94,12 @@ public Builder setModelId(ModelId modelId) { return this; } + @Override + Builder setModelType(String modelType) { + infoBuilder.setModelType(modelType); + return this; + } + @Override public Builder setLabels(Map labels) { infoBuilder.setLabels(labels); diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java index 96a0ed857cf7..c9c7dd8cdda1 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java @@ -27,7 +27,7 @@ import java.util.Objects; /** - * Google BigQuery ML model information. Models are not create directly via the API, but by issuing + * Google BigQuery ML model information. Models are not created directly via the API, but by issuing * a CREATE MODEL query. * * @see CREATE diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java index c8319a8dee53..8286d231fbf7 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java @@ -81,9 +81,10 @@ Boolean getBoolean(Map options) { Dataset getDataset(String projectId, String datasetId, Map options); /** - * Lists the provided project's datasets. Partial information is returned on a dataset - * (datasetReference, friendlyName and id). To get full information use {@link #getDataset(String, - * String, Map)}. + * Lists the provided project's datasets, keyed by page token. + * Partial information is returned on a dataset + * (datasetReference, friendlyName and id). To get full information use + * {@link #getDataset(String, String, Map)}. * * @throws BigQueryException upon failure */ @@ -140,7 +141,8 @@ Boolean getBoolean(Map options) { Table getTable(String projectId, String datasetId, String tableId, Map options); /** - * Lists the dataset's tables. Partial information is returned on a table (tableReference, + * Lists the dataset's tables, keyed by page token. + * Partial information is returned on a table (tableReference, * friendlyName, id and type). To get full information use {@link #getTable(String, String, * String, Map)}. * @@ -172,7 +174,7 @@ Tuple> listTables( Model getModel(String projectId, String datasetId, String modelId, Map options); /** - * Lists the dataset's models. Partial information is returned on a model. + * Lists the dataset's models, keyed by page token. * * @throws BigQueryException upon failure */ From 83769ce546ce5536228faf862e10c0d113e360d1 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Wed, 8 May 2019 11:22:24 -0700 Subject: [PATCH 10/13] formatter + typo --- .../com/google/cloud/bigquery/BigQuery.java | 2 +- .../java/com/google/cloud/bigquery/Model.java | 4 +- .../com/google/cloud/bigquery/ModelInfo.java | 68 ++++++------------- .../cloud/bigquery/spi/v2/BigQueryRpc.java | 14 ++-- .../com/google/cloud/bigquery/ModelTest.java | 25 +++---- 5 files changed, 40 insertions(+), 73 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java index 3750161747dd..c9c2e8226673 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java @@ -133,7 +133,7 @@ enum ModelField implements FieldSelector { LOCATION("location"), MODEL_REFERENCE("modelReference"), TIME_PARTITIONING("timePartitioning"), - TYPE("modelType"), + TYPE("modelType"); static final List REQUIRED_FIELDS = ImmutableList.of(MODEL_REFERENCE); diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java index 7308232db349..7606a5b25e78 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Model.java @@ -128,8 +128,8 @@ public boolean exists() { } /** - * Fetches current model's state from the service. Returns {@code null} if the model does not exist. - * A new {@code Model} is returned. + * Fetches current model's state from the service. Returns {@code null} if the model does not + * exist. A new {@code Model} is returned. * * @param options model options * @return a {@code Model} object with latest information or {@code null} if not found diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java index c9c7dd8cdda1..15df4f492444 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ModelInfo.java @@ -27,11 +27,12 @@ import java.util.Objects; /** - * Google BigQuery ML model information. Models are not created directly via the API, but by issuing + * Google BigQuery ML model information. Models are not created directly via the API, but by issuing * a CREATE MODEL query. * - * @see CREATE - * MODEL statement + * @see CREATE + * MODEL statement */ public class ModelInfo implements Serializable { @@ -62,24 +63,18 @@ public Model apply(ModelInfo ModelInfo) { private final Long expirationTime; private final Labels labels; - /** - * A builder for {@code ModelInfo} objects. - */ + /** A builder for {@code ModelInfo} objects. */ public abstract static class Builder { - /** - * Sets the user description for this model. - **/ + /** Sets the user description for this model. */ public abstract Builder setDescription(String description); - /** - * Sets the user-friendly name for this model. - */ + /** Sets the user-friendly name for this model. */ public abstract Builder setFriendlyName(String friendlyName); /** * Set the time when this model expires, in milliseconds since the epoch. If not present, the - * model persists indefinitely. Expired models will be deleted. + * model persists indefinitely. Expired models will be deleted. */ public abstract Builder setExpirationTime(Long expirationTime); @@ -102,9 +97,7 @@ public abstract static class Builder { abstract Builder setLastModifiedTime(Long lastModifiedTime); - /** - * Creates a {@code ModelInfo} object. - */ + /** Creates a {@code ModelInfo} object. */ public abstract ModelInfo build(); } @@ -120,8 +113,7 @@ static class BuilderImpl extends Builder { private Long expirationTime; private Labels labels = Labels.ZERO; - BuilderImpl() { - } + BuilderImpl() {} BuilderImpl(ModelInfo modelInfo) { this.etag = modelInfo.etag; @@ -221,66 +213,50 @@ public ModelInfo build() { this.labels = builder.labels; } - /** - * Returns the hash of the model resource. - */ + /** Returns the hash of the model resource. */ public String getEtag() { return etag; } - /** - * Returns the model identity. - */ + /** Returns the model identity. */ public ModelId getModelId() { return modelId; } - /** - * Returns the type of the ML model. - */ + /** Returns the type of the ML model. */ public String getModelType() { return modelType; } - /** - * Returns the user description of the model. - */ + /** Returns the user description of the model. */ public String getDescription() { return description; } - /** - * Returns the user-friendly name for the model. - */ + /** Returns the user-friendly name for the model. */ public String getFriendlyName() { return friendlyName; } - /** - * Returns the time when this model was created, in milliseconds since the epoch. - */ + /** Returns the time when this model was created, in milliseconds since the epoch. */ public Long getCreationTime() { return creationTime; } - /** - * Returns the time when this table was last modified, in milliseconds since the epoch. - */ + /** Returns the time when this table was last modified, in milliseconds since the epoch. */ public Long getLastModifiedTime() { return lastModifiedTime; } /** - * Returns this this model expires, in milliseconds since the epoch. If not present, the model - * will persist indefinitely. Expired models will be deleted. + * Returns this this model expires, in milliseconds since the epoch. If not present, the model + * will persist indefinitely. Expired models will be deleted. */ public Long getExpirationTime() { return expirationTime; } - /** - * Returns a map for labels applied to the model. - */ + /** Returns a map for labels applied to the model. */ public Map getLabels() { return labels.userMap(); } @@ -313,8 +289,8 @@ public int hashCode() { public boolean equals(Object obj) { return obj == this || obj != null - && obj.getClass().equals(ModelInfo.class) - && Objects.equals(toPb(), ((ModelInfo) obj).toPb()); + && obj.getClass().equals(ModelInfo.class) + && Objects.equals(toPb(), ((ModelInfo) obj).toPb()); } /** Returns a builder for a {@code ModelInfo} object given table identity. */ diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java index 8286d231fbf7..8255bcfd5a56 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java @@ -81,10 +81,9 @@ Boolean getBoolean(Map options) { Dataset getDataset(String projectId, String datasetId, Map options); /** - * Lists the provided project's datasets, keyed by page token. - * Partial information is returned on a dataset - * (datasetReference, friendlyName and id). To get full information use - * {@link #getDataset(String, String, Map)}. + * Lists the provided project's datasets, keyed by page token. Partial information is returned on + * a dataset (datasetReference, friendlyName and id). To get full information use {@link + * #getDataset(String, String, Map)}. * * @throws BigQueryException upon failure */ @@ -141,10 +140,9 @@ Boolean getBoolean(Map options) { Table getTable(String projectId, String datasetId, String tableId, Map options); /** - * Lists the dataset's tables, keyed by page token. - * Partial information is returned on a table (tableReference, - * friendlyName, id and type). To get full information use {@link #getTable(String, String, - * String, Map)}. + * Lists the dataset's tables, keyed by page token. Partial information is returned on a table + * (tableReference, friendlyName, id and type). To get full information use {@link + * #getTable(String, String, String, Map)}. * * @throws BigQueryException upon failure */ diff --git a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java index e512a6496c82..5ff0f8c89ee7 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java +++ b/google-cloud-clients/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ModelTest.java @@ -16,8 +16,6 @@ package com.google.cloud.bigquery; -import static com.google.cloud.bigquery.ModelIdTest.MODEL; -import static com.google.common.truth.Truth.assertThat; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createStrictMock; import static org.easymock.EasyMock.eq; @@ -30,8 +28,6 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import com.google.api.gax.paging.Page; -import com.google.cloud.PageImpl; import org.junit.After; import org.junit.Test; @@ -40,7 +36,6 @@ public class ModelTest { private BigQuery serviceMockReturnsOptions = createStrictMock(BigQuery.class); private BigQueryOptions mockOptions = createMock(BigQueryOptions.class); - private static final ModelId MODEL_ID = ModelId.of("dataset", "model"); private static final String ETAG = "etag"; private static final Long CREATION_TIME = 10L; @@ -63,7 +58,6 @@ public class ModelTest { private Model expectedModel; private Model model; - private void initializeExpectedModel(int optionsCalls) { expect(serviceMockReturnsOptions.getOptions()).andReturn(mockOptions).times(optionsCalls); replay(serviceMockReturnsOptions); @@ -80,19 +74,19 @@ public void tearDown() throws Exception { verify(bigquery, serviceMockReturnsOptions); } - @Test public void testBuilder() { initializeExpectedModel(2); replay(bigquery); - Model builtModel = new Model.Builder(serviceMockReturnsOptions, MODEL_ID) - .setEtag(ETAG) - .setCreationTime(CREATION_TIME) - .setExpirationTime(EXPIRATION_TIME) - .setLastModifiedTime(LAST_MODIFIED_TIME) - .setDescription(DESCRIPTION) - .setFriendlyName(FRIENDLY_NAME) - .build(); + Model builtModel = + new Model.Builder(serviceMockReturnsOptions, MODEL_ID) + .setEtag(ETAG) + .setCreationTime(CREATION_TIME) + .setExpirationTime(EXPIRATION_TIME) + .setLastModifiedTime(LAST_MODIFIED_TIME) + .setDescription(DESCRIPTION) + .setFriendlyName(FRIENDLY_NAME) + .build(); assertEquals(ETAG, builtModel.getEtag()); assertSame(serviceMockReturnsOptions, builtModel.getBigQuery()); } @@ -195,7 +189,6 @@ public void testDeleteFalse() { assertFalse(model.delete()); } - private void compareModel(Model expected, Model value) { assertEquals(expected, value); compareModelInfo(expected, value); From 47c1fca0e2c8805683a4a3a2563b64675047c3bf Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Wed, 8 May 2019 12:52:03 -0700 Subject: [PATCH 11/13] update pinning of bigquery in google-cloud-clients to v2-rev20190423-1.28.0 --- google-cloud-clients/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-clients/pom.xml b/google-cloud-clients/pom.xml index a24db578a248..a865b8a576b4 100644 --- a/google-cloud-clients/pom.xml +++ b/google-cloud-clients/pom.xml @@ -199,7 +199,7 @@ com.google.apis google-api-services-bigquery - v2-rev20181104-1.27.0 + v2-rev20190423-1.28.0 com.google.apis From ae1242879567a1e99d1e833ed6e7ab0747f08716 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Wed, 8 May 2019 13:10:44 -0700 Subject: [PATCH 12/13] step down from 1.28.0 to 1.27.0 due to bounding on deps --- google-cloud-clients/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-clients/pom.xml b/google-cloud-clients/pom.xml index a865b8a576b4..32245831b9e5 100644 --- a/google-cloud-clients/pom.xml +++ b/google-cloud-clients/pom.xml @@ -199,7 +199,7 @@ com.google.apis google-api-services-bigquery - v2-rev20190423-1.28.0 + v2-rev20190423-1.27.0 com.google.apis From dc0cc2cb29066f292e43ee0246a876f908117069 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Thu, 9 May 2019 09:07:15 -0700 Subject: [PATCH 13/13] backout local pin, will pick up new pin from master --- google-cloud-clients/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-clients/pom.xml b/google-cloud-clients/pom.xml index 32245831b9e5..a24db578a248 100644 --- a/google-cloud-clients/pom.xml +++ b/google-cloud-clients/pom.xml @@ -199,7 +199,7 @@ com.google.apis google-api-services-bigquery - v2-rev20190423-1.27.0 + v2-rev20181104-1.27.0 com.google.apis