Skip to content

Commit

Permalink
feat: add support for clone (#2553)
Browse files Browse the repository at this point in the history
* feat add cupport for clone

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* chore: fix test

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* chore: Clone definition is not a table definition

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* chore: remove CLONE from Table definition

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* chore: fix license header

* chore: check for null

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* chore: add clirr ignored differences

* chore: fix test

---------

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
  • Loading branch information
Neenu1995 and gcf-owl-bot[bot] committed Mar 10, 2023
1 parent 9daab17 commit 2186c64
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 5 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -59,13 +59,13 @@ implementation 'com.google.cloud:google-cloud-bigquery'
If you are using Gradle without BOM, add this to your dependencies:

```Groovy
implementation 'com.google.cloud:google-cloud-bigquery:2.23.1'
implementation 'com.google.cloud:google-cloud-bigquery:2.23.2'
```

If you are using SBT, add this to your dependencies:

```Scala
libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "2.23.1"
libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "2.23.2"
```

## Authentication
Expand Down
6 changes: 6 additions & 0 deletions google-cloud-bigquery/clirr-ignored-differences.xml
Expand Up @@ -44,4 +44,10 @@
<className>com/google/cloud/bigquery/TableInfo*</className>
<method>*DefaultCollation(*)</method>
</difference>

<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/bigquery/TableInfo*</className>
<method>*CloneDefinition(*)</method>
</difference>
</differences>
@@ -0,0 +1,85 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.bigquery;

import com.google.api.client.util.DateTime;
import com.google.api.core.BetaApi;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import java.io.Serializable;
import javax.annotation.Nullable;

@AutoValue
@BetaApi
public abstract class CloneDefinition implements Serializable {

private static final long serialVersionUID = 1460853787400450649L;

public static Builder newBuilder() {
return new AutoValue_CloneDefinition.Builder();
}

static CloneDefinition fromPb(
com.google.api.services.bigquery.model.CloneDefinition cloneDefinition) {
Builder builder = newBuilder();

if (cloneDefinition.getCloneTime() != null) {
builder.setCloneTime(cloneDefinition.getCloneTime().toString());
}
if (cloneDefinition.getBaseTableReference() != null) {
builder.setBaseTableId(TableId.fromPb(cloneDefinition.getBaseTableReference()));
}

return builder.build();
}

@Nullable
public abstract TableId getBaseTableId();

@Nullable
public abstract String getCloneTime();

/** Returns a builder for a Clone table definition. */
@VisibleForTesting
public abstract Builder toBuilder();

com.google.api.services.bigquery.model.CloneDefinition toPb() {

com.google.api.services.bigquery.model.CloneDefinition cloneDefinition =
new com.google.api.services.bigquery.model.CloneDefinition();
cloneDefinition.setBaseTableReference(getBaseTableId().toPb());
cloneDefinition.setCloneTime(DateTime.parseRfc3339(getCloneTime()));

return cloneDefinition;
}

@AutoValue.Builder
public abstract static class Builder {

/** Reference describing the ID of the table that was Cloned. * */
public abstract Builder setBaseTableId(TableId baseTableId);

/**
* The time at which the base table was Cloned. This value is reported in the JSON response
* using RFC3339 format. *
*/
public abstract Builder setCloneTime(String dateTime);

/** Creates a {@code CloneDefinition} object. */
public abstract CloneDefinition build();
}
}
Expand Up @@ -128,8 +128,8 @@ public Builder setDestinationTable(TableId destinationTable) {
}

/**
* Sets the supported operation types (COPY, SNAPSHOT or RESTORE) in table copy job. More info:
* https://cloud.google.com/bigquery/docs/reference/rest/v2/Job#operationtype
* Sets the supported operation types (COPY, CLONE, SNAPSHOT or RESTORE) in table copy job. More
* info: https://cloud.google.com/bigquery/docs/reference/rest/v2/Job#operationtype
*/
public Builder setOperationType(String operationType) {
this.operationType = operationType;
Expand Down
Expand Up @@ -162,6 +162,12 @@ public Builder setDefaultCollation(String defaultCollation) {
return this;
}

@Override
public TableInfo.Builder setCloneDefinition(CloneDefinition cloneDefinition) {
infoBuilder.setCloneDefinition(cloneDefinition);
return this;
}

@Override
public Table build() {
return new Table(bigquery, infoBuilder);
Expand Down
Expand Up @@ -74,6 +74,8 @@ public Table apply(TableInfo tableInfo) {
private final Boolean requirePartitionFilter;
private final String defaultCollation;

private final CloneDefinition cloneDefinition;

/** A builder for {@code TableInfo} objects. */
public abstract static class Builder {

Expand Down Expand Up @@ -138,6 +140,8 @@ public Builder setRequirePartitionFilter(Boolean requirePartitionFilter) {
}

public abstract Builder setDefaultCollation(String defaultCollation);

public abstract Builder setCloneDefinition(CloneDefinition cloneDefinition);
}

static class BuilderImpl extends Builder {
Expand All @@ -159,6 +163,7 @@ static class BuilderImpl extends Builder {
private Labels labels = Labels.ZERO;
private Boolean requirePartitionFilter;
private String defaultCollation;
private CloneDefinition cloneDefinition;

BuilderImpl() {}

Expand All @@ -180,6 +185,7 @@ static class BuilderImpl extends Builder {
this.labels = tableInfo.labels;
this.requirePartitionFilter = tableInfo.requirePartitionFilter;
this.defaultCollation = tableInfo.defaultCollation;
this.cloneDefinition = tableInfo.cloneDefinition;
}

BuilderImpl(Table tablePb) {
Expand All @@ -205,6 +211,9 @@ static class BuilderImpl extends Builder {
this.labels = Labels.fromPb(tablePb.getLabels());
this.requirePartitionFilter = tablePb.getRequirePartitionFilter();
this.defaultCollation = tablePb.getDefaultCollation();
if (tablePb.getCloneDefinition() != null) {
this.cloneDefinition = CloneDefinition.fromPb(tablePb.getCloneDefinition());
}
}

@Override
Expand Down Expand Up @@ -309,6 +318,11 @@ public Builder setDefaultCollation(String defaultCollation) {
return this;
}

public Builder setCloneDefinition(CloneDefinition cloneDefinition) {
this.cloneDefinition = cloneDefinition;
return this;
}

@Override
public TableInfo build() {
return new TableInfo(this);
Expand All @@ -333,6 +347,7 @@ public TableInfo build() {
this.labels = builder.labels;
this.requirePartitionFilter = builder.requirePartitionFilter;
this.defaultCollation = builder.defaultCollation;
this.cloneDefinition = builder.cloneDefinition;
}

/** Returns the hash of the table resource. */
Expand Down Expand Up @@ -439,6 +454,10 @@ public String getDefaultCollation() {
return defaultCollation;
}

public CloneDefinition getCloneDefinition() {
return cloneDefinition;
}

/** Returns a builder for the table object. */
public Builder toBuilder() {
return new BuilderImpl(this);
Expand All @@ -464,6 +483,7 @@ public String toString() {
.add("labels", labels)
.add("requirePartitionFilter", requirePartitionFilter)
.add("defaultCollation", defaultCollation)
.add("cloneDefinition", cloneDefinition)
.toString();
}

Expand Down Expand Up @@ -528,6 +548,9 @@ Table toPb() {
if (defaultCollation != null) {
tablePb.setDefaultCollation(defaultCollation);
}
if (cloneDefinition != null) {
tablePb.setCloneDefinition(cloneDefinition.toPb());
}
return tablePb;
}

Expand Down
@@ -0,0 +1,58 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.bigquery;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class CloneDefinitionTest {
private static final TableId BASE_TABLE_ID = TableId.of("DATASET_NAME", "BASE_TABLE_NAME");
private static final String CLONE_TIME = "2021-05-19T11:32:26.553Z";
private static final CloneDefinition CLONETABLE_DEFINITION =
CloneDefinition.newBuilder().setBaseTableId(BASE_TABLE_ID).setCloneTime(CLONE_TIME).build();

@Test
public void testToBuilder() {
compareCloneTableDefinition(CLONETABLE_DEFINITION, CLONETABLE_DEFINITION.toBuilder().build());
CloneDefinition cloneTableDefinition =
CLONETABLE_DEFINITION.toBuilder().setCloneTime("2021-05-20T11:32:26.553Z").build();
assertEquals("2021-05-20T11:32:26.553Z", cloneTableDefinition.getCloneTime());
}

@Test
public void testBuilder() {
assertEquals(BASE_TABLE_ID, CLONETABLE_DEFINITION.getBaseTableId());
assertEquals(CLONE_TIME, CLONETABLE_DEFINITION.getCloneTime());
CloneDefinition cloneDefinition =
CloneDefinition.newBuilder().setBaseTableId(BASE_TABLE_ID).setCloneTime(CLONE_TIME).build();
assertEquals(CLONETABLE_DEFINITION, cloneDefinition);
}

@Test
public void testToAndFromPb() {
CloneDefinition cloneDefinition = CLONETABLE_DEFINITION.toBuilder().build();
assertTrue(CloneDefinition.fromPb(cloneDefinition.toPb()) instanceof CloneDefinition);
compareCloneTableDefinition(cloneDefinition, CloneDefinition.fromPb(cloneDefinition.toPb()));
}

private void compareCloneTableDefinition(CloneDefinition expected, CloneDefinition value) {
assertEquals(expected.getBaseTableId(), value.getBaseTableId());
assertEquals(expected.getCloneTime(), value.getCloneTime());
}
}
Expand Up @@ -54,6 +54,7 @@
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryResult;
import com.google.cloud.bigquery.BigQuerySQLException;
import com.google.cloud.bigquery.CloneDefinition;
import com.google.cloud.bigquery.Clustering;
import com.google.cloud.bigquery.Connection;
import com.google.cloud.bigquery.ConnectionProperty;
Expand Down Expand Up @@ -4334,6 +4335,7 @@ public void testSnapshotTableCopyJob() throws InterruptedException {
assertNotNull(snapshotTable);
assertEquals(snapshotTableId.getDataset(), snapshotTable.getTableId().getDataset());
assertEquals(snapshotTableName, snapshotTable.getTableId().getTable());
System.out.println(snapshotTable.getDefinition());
assertTrue(snapshotTable.getDefinition() instanceof SnapshotTableDefinition);
assertEquals(DDL_TABLE_SCHEMA, snapshotTable.getDefinition().getSchema());
assertNotNull(((SnapshotTableDefinition) snapshotTable.getDefinition()).getSnapshotTime());
Expand Down Expand Up @@ -5179,4 +5181,56 @@ public void testCreateExternalTableWithReferenceFileSchemaParquet() {
boolean success = bigquery.delete(tableId);
assertEquals(true, success);
}

@Test
public void testCloneTableCopyJob() throws InterruptedException {
String sourceTableName = "test_copy_job_base_table";
String ddlTableName = TABLE_ID_DDL.getTable();
String cloneTableName = String.format("test_clone_table");
// Create source table with some data in it
String ddlQuery =
String.format(
"CREATE OR REPLACE TABLE %s ("
+ "TimestampField TIMESTAMP OPTIONS(description='TimestampDescription'), "
+ "StringField STRING OPTIONS(description='StringDescription'), "
+ "BooleanField BOOLEAN OPTIONS(description='BooleanDescription') "
+ ") AS SELECT * FROM %s",
sourceTableName, ddlTableName);
QueryJobConfiguration ddlConfig =
QueryJobConfiguration.newBuilder(ddlQuery).setDefaultDataset(DatasetId.of(DATASET)).build();
TableId sourceTableId = TableId.of(DATASET, sourceTableName);
TableResult result = bigquery.query(ddlConfig);
assertEquals(DDL_TABLE_SCHEMA, result.getSchema());
Table remoteTable = bigquery.getTable(DATASET, sourceTableName);
assertNotNull(remoteTable);

// Create clone table using source table as the base table
TableId cloneTableId = TableId.of(DATASET, cloneTableName);
CopyJobConfiguration cloneConfiguration =
CopyJobConfiguration.newBuilder(cloneTableId, sourceTableId)
.setOperationType("CLONE")
.build();
Job createdJob = bigquery.create(JobInfo.of(cloneConfiguration));
CopyJobConfiguration createdConfiguration = createdJob.getConfiguration();
assertNotNull(createdConfiguration.getSourceTables());
assertNotNull(createdConfiguration.getOperationType());
assertNotNull(createdConfiguration.getDestinationTable());
Job completedJob = createdJob.waitFor();
assertNull(completedJob.getStatus().getError());

Table cloneTable = bigquery.getTable(DATASET, cloneTableName);
assertNotNull(cloneTable);
assertEquals(cloneTableId.getDataset(), cloneTable.getTableId().getDataset());
assertEquals(cloneTableName, cloneTable.getTableId().getTable());
assertEquals(TableDefinition.Type.TABLE, cloneTable.getDefinition().getType());
assertTrue(cloneTable.getDefinition() instanceof StandardTableDefinition);
assertEquals(DDL_TABLE_SCHEMA, cloneTable.getDefinition().getSchema());
assertTrue(cloneTable.getCloneDefinition() instanceof CloneDefinition);
assertEquals(sourceTableName, cloneTable.getCloneDefinition().getBaseTableId().getTable());
assertNotNull(cloneTable.getCloneDefinition().getCloneTime());

// Clean up
assertTrue(remoteTable.delete());
assertTrue(cloneTable.delete());
}
}
Expand Up @@ -47,7 +47,7 @@ public class ITRemoteUDFTest {

private static final String ID = UUID.randomUUID().toString().substring(0, 8);
private static final String PROJECT_ID = ServiceOptions.getDefaultProjectId();
private static final String CONNECTION_ID = "test-connectin-id-" + ID;
private static final String CONNECTION_ID = "test-connection-id-" + ID;
private static final String LOCATION = "US";
private static final String PARENT = LocationName.of(PROJECT_ID, LOCATION).toString();
private static final String REMOTE_ENDPOINT = "https://aaabbbccc-uc.a.run.app";
Expand Down

0 comments on commit 2186c64

Please sign in to comment.