Skip to content

Commit

Permalink
feat: add field in HivePartitioningOptions (#2678)
Browse files Browse the repository at this point in the history
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
- [ v] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/java-bigquery/issues/new/choose) before writing your code!  That way we can discuss the change, evaluate designs, and agree on the general idea
- [ v] Ensure the tests and linter pass
- [ v] Code coverage does not decrease (if any source code was changed)
- [v ] Appropriate docs were updated (if necessary)

Fixes #2677 ☕️
  • Loading branch information
davidrabinowitz committed May 4, 2023
1 parent e1326c8 commit 4165e55
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 4 deletions.
Expand Up @@ -17,6 +17,7 @@
package com.google.cloud.bigquery;

import com.google.common.base.MoreObjects;
import java.util.List;
import java.util.Objects;

/** HivePartitioningOptions currently supported types include: AVRO, CSV, JSON, ORC and Parquet. */
Expand All @@ -25,19 +26,22 @@ public final class HivePartitioningOptions {
private final String mode;
private final Boolean requirePartitionFilter;
private final String sourceUriPrefix;
private final List<String> fields;

public static final class Builder {

private String mode;
private Boolean requirePartitionFilter;
private String sourceUriPrefix;
private List<String> fields;

private Builder() {}

private Builder(HivePartitioningOptions options) {
this.mode = options.mode;
this.requirePartitionFilter = options.requirePartitionFilter;
this.sourceUriPrefix = options.sourceUriPrefix;
this.fields = options.fields;
}

/**
Expand Down Expand Up @@ -78,6 +82,19 @@ public Builder setSourceUriPrefix(String sourceUriPrefix) {
return this;
}

/**
* [Output-only] For permanent external tables, this field is populated with the hive partition
* keys in the order they were inferred.
*
* <p>The types of the partition keys can be deduced by checking the table schema (which will
* include the partition keys). Not every API will populate this field in the output. For
* example, Tables.Get will populate it, but Tables.List will not contain this field.
*/
public Builder setFields(List<String> fields) {
this.fields = fields;
return this;
}

/** Creates a {@link HivePartitioningOptions} object. */
public HivePartitioningOptions build() {
return new HivePartitioningOptions(this);
Expand All @@ -88,6 +105,7 @@ private HivePartitioningOptions(Builder builder) {
this.mode = builder.mode;
this.requirePartitionFilter = builder.requirePartitionFilter;
this.sourceUriPrefix = builder.sourceUriPrefix;
this.fields = builder.fields;
}

/* Returns the mode of hive partitioning */
Expand All @@ -108,6 +126,11 @@ public String getSourceUriPrefix() {
return sourceUriPrefix;
}

/* Returns the fields of hive partitioning */
public List<String> getFields() {
return fields;
}

/** Returns a builder for the {@link HivePartitioningOptions} object. */
public Builder toBuilder() {
return new Builder(this);
Expand Down Expand Up @@ -135,13 +158,13 @@ public boolean equals(Object obj) {
&& Objects.equals(mode, ((HivePartitioningOptions) obj).getMode())
&& Objects.equals(
requirePartitionFilter, ((HivePartitioningOptions) obj).getRequirePartitionFilter())
&& Objects.equals(
sourceUriPrefix, ((HivePartitioningOptions) obj).getSourceUriPrefix());
&& Objects.equals(sourceUriPrefix, ((HivePartitioningOptions) obj).getSourceUriPrefix())
&& Objects.equals(fields, ((HivePartitioningOptions) obj).getFields());
}

@Override
public int hashCode() {
return Objects.hash(mode, sourceUriPrefix);
return Objects.hash(mode, sourceUriPrefix, fields);
}

com.google.api.services.bigquery.model.HivePartitioningOptions toPb() {
Expand All @@ -150,6 +173,7 @@ com.google.api.services.bigquery.model.HivePartitioningOptions toPb() {
options.setMode(mode);
options.setRequirePartitionFilter(requirePartitionFilter);
options.setSourceUriPrefix(sourceUriPrefix);
options.setFields(fields);
return options;
}

Expand All @@ -165,6 +189,9 @@ static HivePartitioningOptions fromPb(
if (options.getSourceUriPrefix() != null) {
builder.setSourceUriPrefix(options.getSourceUriPrefix());
}
if (options.getFields() != null) {
builder.setFields(options.getFields());
}
return builder.build();
}
}
Expand Up @@ -18,18 +18,22 @@

import static com.google.common.truth.Truth.assertThat;

import java.util.Arrays;
import java.util.List;
import org.junit.Test;

public class HivePartitioningOptionsTest {

private static final String MODE = "STRING";
private static final String SOURCE_URI_PREFIX = "gs://bucket/path_to_table";
private static final Boolean REQUIRE_PARTITION_FILTER = true;
private static final List<String> FIELDS = Arrays.asList("FIELD1", "FIELD2");
private static final HivePartitioningOptions HIVE_PARTITIONING_OPTIONS =
HivePartitioningOptions.newBuilder()
.setMode(MODE)
.setRequirePartitionFilter(REQUIRE_PARTITION_FILTER)
.setSourceUriPrefix(SOURCE_URI_PREFIX)
.setFields(FIELDS)
.build();

@Test
Expand Down
Expand Up @@ -5233,4 +5233,48 @@ public void testCloneTableCopyJob() throws InterruptedException {
assertTrue(remoteTable.delete());
assertTrue(cloneTable.delete());
}

@Test
public void testHivePartitioningOptionsFieldsFieldExistence() throws InterruptedException {
String tableName = "hive_partitioned_external_table";

// Create data on GCS
String sourceDirectory = "bigquery/hive-partitioning-table/example";
BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, sourceDirectory + "/key=foo/data.json").build();
assertNotNull(
"Failed to upload JSON to GCS",
storage.create(blobInfo, "{\"name\":\"bar\"}".getBytes(StandardCharsets.UTF_8)));
String sourceUri = "gs://" + BUCKET + "/" + sourceDirectory + "/*";
String sourceUriPrefix = "gs://" + BUCKET + "/" + sourceDirectory + "/";

// Create the external table
HivePartitioningOptions hivePartitioningOptions =
HivePartitioningOptions.newBuilder()
.setMode("AUTO")
.setRequirePartitionFilter(true)
.setSourceUriPrefix(sourceUriPrefix)
.build();

TableId tableId = TableId.of(DATASET, tableName);
ExternalTableDefinition customTable =
ExternalTableDefinition.newBuilder(sourceUri, FormatOptions.json())
.setAutodetect(true)
.setHivePartitioningOptions(hivePartitioningOptions)
.build();
bigquery.create(TableInfo.of(tableId, customTable));

// Validate the existence of the field HivePartitioningOptions.fields
Table table = bigquery.getTable(tableId);
assertThat(table).isNotNull();
HivePartitioningOptions options =
((ExternalTableDefinition) table.getDefinition()).getHivePartitioningOptions();
List<String> fields = options.getFields();
assertThat(fields).isNotNull();
assertThat(fields).hasSize(1);
assertThat(fields).contains("key");

// Clean up
assertTrue(table.delete());
assertTrue(storage.delete(blobInfo.getBlobId()));
}
}
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -54,7 +54,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<github.global.server>github</github.global.server>
<site.installationModule>google-cloud-bigquery-parent</site.installationModule>
<google-api-services-bigquery.version>v2-rev20230408-2.0.0</google-api-services-bigquery.version>
<google-api-services-bigquery.version>v2-rev20230422-2.0.0</google-api-services-bigquery.version>
<google.cloud.shared-dependencies.version>3.8.0</google.cloud.shared-dependencies.version>
<arrow.version>11.0.0</arrow.version>
</properties>
Expand Down

0 comments on commit 4165e55

Please sign in to comment.