Skip to content

Commit febfc1f

Browse files
feat: Support RANGE schema (#3043)
* feat: Add support for creating tables with range type schema * feat: Add support for creating tables with range type schema * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * feat: Use location in BigQueryOption as the default for query * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 7a1bbd2 commit febfc1f

File tree

6 files changed

+160
-2
lines changed

6 files changed

+160
-2
lines changed

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Field.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public TableFieldSchema apply(Field field) {
6464
private final Long precision;
6565
private final String defaultValueExpression;
6666
private final String collation;
67+
private final FieldElementType rangeElementType;
6768

6869
/**
6970
* Mode for a BigQuery Table field. {@link Mode#NULLABLE} fields can be set to {@code null},
@@ -89,6 +90,7 @@ public static final class Builder {
8990
private Long precision;
9091
private String defaultValueExpression;
9192
private String collation;
93+
private FieldElementType rangeElementType;
9294

9395
private Builder() {}
9496

@@ -104,6 +106,7 @@ private Builder(Field field) {
104106
this.precision = field.precision;
105107
this.defaultValueExpression = field.defaultValueExpression;
106108
this.collation = field.collation;
109+
this.rangeElementType = field.rangeElementType;
107110
}
108111

109112
/**
@@ -292,6 +295,12 @@ public Builder setCollation(String collation) {
292295
return this;
293296
}
294297

298+
/** Optional. Field range element type can be set only when the type of field is RANGE. */
299+
public Builder setRangeElementType(FieldElementType rangeElementType) {
300+
this.rangeElementType = rangeElementType;
301+
return this;
302+
}
303+
295304
/** Creates a {@code Field} object. */
296305
public Field build() {
297306
return new Field(this);
@@ -310,6 +319,7 @@ private Field(Builder builder) {
310319
this.precision = builder.precision;
311320
this.defaultValueExpression = builder.defaultValueExpression;
312321
this.collation = builder.collation;
322+
this.rangeElementType = builder.rangeElementType;
313323
}
314324

315325
/** Returns the field name. */
@@ -369,6 +379,11 @@ public String getCollation() {
369379
return collation;
370380
}
371381

382+
/** Return the range element type the field. */
383+
public FieldElementType getRangeElementType() {
384+
return rangeElementType;
385+
}
386+
372387
/**
373388
* Returns the list of sub-fields if {@link #getType()} is a {@link LegacySQLTypeName#RECORD}.
374389
* Returns {@code null} otherwise.
@@ -395,12 +410,13 @@ public String toString() {
395410
.add("precision", precision)
396411
.add("defaultValueExpression", defaultValueExpression)
397412
.add("collation", collation)
413+
.add("rangeElementType", rangeElementType)
398414
.toString();
399415
}
400416

401417
@Override
402418
public int hashCode() {
403-
return Objects.hash(name, type, mode, description, policyTags);
419+
return Objects.hash(name, type, mode, description, policyTags, rangeElementType);
404420
}
405421

406422
@Override
@@ -484,6 +500,9 @@ TableFieldSchema toPb() {
484500
if (collation != null) {
485501
fieldSchemaPb.setCollation(collation);
486502
}
503+
if (rangeElementType != null) {
504+
fieldSchemaPb.setRangeElementType(rangeElementType.toPb());
505+
}
487506
return fieldSchemaPb;
488507
}
489508

@@ -519,6 +538,10 @@ static Field fromPb(TableFieldSchema fieldSchemaPb) {
519538
if (fieldSchemaPb.getCollation() != null) {
520539
fieldBuilder.setCollation(fieldSchemaPb.getCollation());
521540
}
541+
if (fieldSchemaPb.getRangeElementType() != null) {
542+
fieldBuilder.setRangeElementType(
543+
FieldElementType.fromPb(fieldSchemaPb.getRangeElementType()));
544+
}
522545
return fieldBuilder.build();
523546
}
524547
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.bigquery;
17+
18+
import com.google.api.services.bigquery.model.TableFieldSchema;
19+
import com.google.auto.value.AutoValue;
20+
import java.io.Serializable;
21+
import javax.annotation.Nullable;
22+
23+
@AutoValue
24+
public abstract class FieldElementType implements Serializable {
25+
26+
private static final long serialVersionUID = 1L;
27+
28+
/**
29+
* The subtype of the RANGE, if the field type is RANGE.
30+
*
31+
* @return value or {@code null} for none
32+
*/
33+
@Nullable
34+
public abstract String getType();
35+
36+
public abstract FieldElementType.Builder toBuilder();
37+
38+
@AutoValue.Builder
39+
public abstract static class Builder {
40+
41+
public abstract FieldElementType.Builder setType(String type);
42+
43+
public abstract FieldElementType build();
44+
}
45+
46+
public static Builder newBuilder() {
47+
return new AutoValue_FieldElementType.Builder();
48+
}
49+
50+
TableFieldSchema.RangeElementType toPb() {
51+
TableFieldSchema.RangeElementType rangeElementTypePb = new TableFieldSchema.RangeElementType();
52+
rangeElementTypePb.setType(getType());
53+
return rangeElementTypePb;
54+
}
55+
56+
static FieldElementType fromPb(TableFieldSchema.RangeElementType rangeElementTypePb) {
57+
// Treat a FieldElementType message without a Type subfield as invalid.
58+
if (rangeElementTypePb.getType() != null) {
59+
return newBuilder().setType(rangeElementTypePb.getType()).build();
60+
}
61+
return null;
62+
}
63+
}

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LegacySQLTypeName.java

+4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ public LegacySQLTypeName apply(String constant) {
100100
public static final LegacySQLTypeName INTERVAL =
101101
type.createAndRegister("INTERVAL").setStandardType(StandardSQLTypeName.INTERVAL);
102102

103+
/** Represents a contiguous range of values. */
104+
public static final LegacySQLTypeName RANGE =
105+
type.createAndRegister("RANGE").setStandardType(StandardSQLTypeName.RANGE);
106+
103107
private static Map<StandardSQLTypeName, LegacySQLTypeName> standardToLegacyMap = new HashMap<>();
104108

105109
static {

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/StandardSQLTypeName.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,7 @@ public enum StandardSQLTypeName {
6060
/** Represents JSON data. */
6161
JSON,
6262
/** Represents duration or amount of time. */
63-
INTERVAL
63+
INTERVAL,
64+
/** Represents a contiguous range of values. */
65+
RANGE
6466
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.bigquery;
17+
18+
import static org.junit.Assert.assertEquals;
19+
20+
import org.junit.Test;
21+
22+
public class FieldElementTypeTest {
23+
private static final FieldElementType FIELD_ELEMENT_TYPE =
24+
FieldElementType.newBuilder().setType("DATE").build();
25+
26+
@Test
27+
public void testToBuilder() {
28+
compareFieldElementType(FIELD_ELEMENT_TYPE, FIELD_ELEMENT_TYPE.toBuilder().build());
29+
}
30+
31+
@Test
32+
public void testBuilder() {
33+
assertEquals("DATE", FIELD_ELEMENT_TYPE.getType());
34+
}
35+
36+
@Test
37+
public void testFromAndPb() {
38+
assertEquals(FIELD_ELEMENT_TYPE, FieldElementType.fromPb(FIELD_ELEMENT_TYPE.toPb()));
39+
}
40+
41+
private void compareFieldElementType(FieldElementType expected, FieldElementType value) {
42+
assertEquals(expected.getType(), value.getType());
43+
assertEquals(expected.hashCode(), value.hashCode());
44+
assertEquals(expected.toString(), value.toString());
45+
}
46+
}

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java

+20
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import com.google.cloud.bigquery.ExtractJobConfiguration;
7373
import com.google.cloud.bigquery.Field;
7474
import com.google.cloud.bigquery.Field.Mode;
75+
import com.google.cloud.bigquery.FieldElementType;
7576
import com.google.cloud.bigquery.FieldList;
7677
import com.google.cloud.bigquery.FieldValue;
7778
import com.google.cloud.bigquery.FieldValue.Attribute;
@@ -1246,6 +1247,25 @@ public void testIntervalType() throws InterruptedException {
12461247
}
12471248
}
12481249

1250+
@Test
1251+
public void testRangeType() throws InterruptedException {
1252+
String tableName = "test_create_table_rangetype";
1253+
TableId tableId = TableId.of(DATASET, tableName);
1254+
Schema schema =
1255+
Schema.of(
1256+
Field.newBuilder("rangeField", StandardSQLTypeName.RANGE)
1257+
.setRangeElementType(FieldElementType.newBuilder().setType("DATETIME").build())
1258+
.build());
1259+
StandardTableDefinition standardTableDefinition = StandardTableDefinition.of(schema);
1260+
try {
1261+
// Create a table with a RANGE column.
1262+
Table createdTable = bigquery.create(TableInfo.of(tableId, standardTableDefinition));
1263+
assertNotNull(createdTable);
1264+
} finally {
1265+
assertTrue(bigquery.delete(tableId));
1266+
}
1267+
}
1268+
12491269
@Test
12501270
public void testCreateTableWithConstraints() {
12511271
String tableName = "test_create_table_with_constraints";

0 commit comments

Comments
 (0)