Skip to content

Commit 398c3dc

Browse files
committed
feat(bigquery): add QueryResultsFormat and ArrowSerializationOptions configurations
1 parent d945a69 commit 398c3dc

5 files changed

Lines changed: 220 additions & 5 deletions

File tree

google-cloud-jar-parent/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
<dependency>
143143
<groupId>com.google.apis</groupId>
144144
<artifactId>google-api-services-bigquery</artifactId>
145-
<version>v2-rev20260612-2.0.0</version>
145+
<version>v2-rev20260707-2.0.0</version>
146146
</dependency>
147147

148148
</dependencies>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2026 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+
17+
package com.google.cloud.bigquery;
18+
19+
import com.google.api.core.BetaApi;
20+
import java.io.Serializable;
21+
import java.util.Objects;
22+
23+
/** Options specific to the Apache Arrow output format. */
24+
@BetaApi
25+
public final class ArrowSerializationOptions implements Serializable {
26+
27+
private static final long serialVersionUID = 1L;
28+
29+
private final String bufferCompression;
30+
private final String picosTimestampPrecision;
31+
32+
private ArrowSerializationOptions(Builder builder) {
33+
this.bufferCompression = builder.bufferCompression;
34+
this.picosTimestampPrecision = builder.picosTimestampPrecision;
35+
}
36+
37+
public String getBufferCompression() {
38+
return bufferCompression;
39+
}
40+
41+
public String getPicosTimestampPrecision() {
42+
return picosTimestampPrecision;
43+
}
44+
45+
public static Builder newBuilder() {
46+
return new Builder();
47+
}
48+
49+
@Override
50+
public String toString() {
51+
return com.google.common.base.MoreObjects.toStringHelper(this)
52+
.add("bufferCompression", bufferCompression)
53+
.add("picosTimestampPrecision", picosTimestampPrecision)
54+
.toString();
55+
}
56+
57+
@Override
58+
public boolean equals(Object o) {
59+
if (this == o) {
60+
return true;
61+
}
62+
if (o == null || getClass() != o.getClass()) {
63+
return false;
64+
}
65+
ArrowSerializationOptions that = (ArrowSerializationOptions) o;
66+
return Objects.equals(bufferCompression, that.bufferCompression)
67+
&& Objects.equals(picosTimestampPrecision, that.picosTimestampPrecision);
68+
}
69+
70+
@Override
71+
public int hashCode() {
72+
return Objects.hash(bufferCompression, picosTimestampPrecision);
73+
}
74+
75+
com.google.api.services.bigquery.model.ArrowSerializationOptions toPb() {
76+
com.google.api.services.bigquery.model.ArrowSerializationOptions optionsPb =
77+
new com.google.api.services.bigquery.model.ArrowSerializationOptions();
78+
if (bufferCompression != null) {
79+
optionsPb.setBufferCompression(bufferCompression);
80+
}
81+
if (picosTimestampPrecision != null) {
82+
optionsPb.setPicosTimestampPrecision(picosTimestampPrecision);
83+
}
84+
return optionsPb;
85+
}
86+
87+
static ArrowSerializationOptions fromPb(
88+
com.google.api.services.bigquery.model.ArrowSerializationOptions optionsPb) {
89+
if (optionsPb == null) {
90+
return null;
91+
}
92+
return newBuilder()
93+
.setBufferCompression(optionsPb.getBufferCompression())
94+
.setPicosTimestampPrecision(optionsPb.getPicosTimestampPrecision())
95+
.build();
96+
}
97+
98+
public static final class Builder {
99+
private String bufferCompression;
100+
private String picosTimestampPrecision;
101+
102+
private Builder() {}
103+
104+
public Builder setBufferCompression(String bufferCompression) {
105+
this.bufferCompression = bufferCompression;
106+
return this;
107+
}
108+
109+
public Builder setPicosTimestampPrecision(String picosTimestampPrecision) {
110+
this.picosTimestampPrecision = picosTimestampPrecision;
111+
return this;
112+
}
113+
114+
public ArrowSerializationOptions build() {
115+
return new ArrowSerializationOptions(this);
116+
}
117+
}
118+
}

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

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public final class QueryJobConfiguration extends JobConfiguration {
7575
private final Long maxResults;
7676
private final JobCreationMode jobCreationMode;
7777
private final String reservation;
78+
private final QueryResultsFormat queryResultsFormat;
79+
private final ArrowSerializationOptions arrowSerializationOptions;
7880

7981
/**
8082
* Priority levels for a query. If not specified the priority is assumed to be {@link
@@ -144,6 +146,8 @@ public static final class Builder
144146
private Long maxResults;
145147
private JobCreationMode jobCreationMode;
146148
private String reservation;
149+
private QueryResultsFormat queryResultsFormat;
150+
private ArrowSerializationOptions arrowSerializationOptions;
147151

148152
private Builder() {
149153
super(Type.QUERY);
@@ -181,6 +185,8 @@ private Builder(QueryJobConfiguration jobConfiguration) {
181185
this.maxResults = jobConfiguration.maxResults;
182186
this.jobCreationMode = jobConfiguration.jobCreationMode;
183187
this.reservation = jobConfiguration.reservation;
188+
this.queryResultsFormat = jobConfiguration.queryResultsFormat;
189+
this.arrowSerializationOptions = jobConfiguration.arrowSerializationOptions;
184190
}
185191

186192
private Builder(com.google.api.services.bigquery.model.JobConfiguration configurationPb) {
@@ -701,6 +707,17 @@ public Builder setReservation(String reservation) {
701707
return this;
702708
}
703709

710+
public Builder setQueryResultsFormat(QueryResultsFormat queryResultsFormat) {
711+
this.queryResultsFormat = queryResultsFormat;
712+
return this;
713+
}
714+
715+
public Builder setArrowSerializationOptions(
716+
ArrowSerializationOptions arrowSerializationOptions) {
717+
this.arrowSerializationOptions = arrowSerializationOptions;
718+
return this;
719+
}
720+
704721
public QueryJobConfiguration build() {
705722
return new QueryJobConfiguration(this);
706723
}
@@ -747,6 +764,8 @@ private QueryJobConfiguration(Builder builder) {
747764
this.maxResults = builder.maxResults;
748765
this.jobCreationMode = builder.jobCreationMode;
749766
this.reservation = builder.reservation;
767+
this.queryResultsFormat = builder.queryResultsFormat;
768+
this.arrowSerializationOptions = builder.arrowSerializationOptions;
750769
}
751770

752771
/**
@@ -973,6 +992,14 @@ public Builder toBuilder() {
973992
return new Builder(this);
974993
}
975994

995+
public QueryResultsFormat getQueryResultsFormat() {
996+
return queryResultsFormat;
997+
}
998+
999+
public ArrowSerializationOptions getArrowSerializationOptions() {
1000+
return arrowSerializationOptions;
1001+
}
1002+
9761003
@Override
9771004
ToStringHelper toStringHelper() {
9781005
return super.toStringHelper()
@@ -1004,13 +1031,23 @@ ToStringHelper toStringHelper() {
10041031
.add("rangePartitioning", rangePartitioning)
10051032
.add("connectionProperties", connectionProperties)
10061033
.add("jobCreationMode", jobCreationMode)
1007-
.add("reservation", reservation);
1034+
.add("reservation", reservation)
1035+
.add("queryResultsFormat", queryResultsFormat)
1036+
.add("arrowSerializationOptions", arrowSerializationOptions);
10081037
}
10091038

10101039
@Override
10111040
public boolean equals(Object obj) {
1012-
return obj == this
1013-
|| obj instanceof QueryJobConfiguration && baseEquals((QueryJobConfiguration) obj);
1041+
if (obj == this) {
1042+
return true;
1043+
}
1044+
if (obj == null || !(obj instanceof QueryJobConfiguration)) {
1045+
return false;
1046+
}
1047+
QueryJobConfiguration other = (QueryJobConfiguration) obj;
1048+
return baseEquals(other)
1049+
&& Objects.equals(queryResultsFormat, other.queryResultsFormat)
1050+
&& Objects.equals(arrowSerializationOptions, other.arrowSerializationOptions);
10141051
}
10151052

10161053
@Override
@@ -1043,7 +1080,9 @@ public int hashCode() {
10431080
labels,
10441081
rangePartitioning,
10451082
connectionProperties,
1046-
reservation);
1083+
reservation,
1084+
queryResultsFormat,
1085+
arrowSerializationOptions);
10471086
}
10481087

10491088
@Override
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2026 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+
17+
package com.google.cloud.bigquery;
18+
19+
import com.google.api.core.BetaApi;
20+
21+
/** The format of the query results. */
22+
@BetaApi
23+
public enum QueryResultsFormat {
24+
/** Serialized row data in Apache Arrow format. */
25+
ARROW,
26+
27+
/** Default encoding of results as JSON struct array. */
28+
STRUCT_ENCODING
29+
}

java-bigquery/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/QueryJobConfigurationTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,35 @@ public void testJobCreationMode() {
241241
QUERY_JOB_CONFIGURATION_SET_JOB_CREATION_MODE.toBuilder().build());
242242
}
243243

244+
@Test
245+
public void testArrowConfigurations() {
246+
QueryResultsFormat format = QueryResultsFormat.ARROW;
247+
ArrowSerializationOptions options =
248+
ArrowSerializationOptions.newBuilder()
249+
.setBufferCompression("LZ4")
250+
.setPicosTimestampPrecision("PRECISION_MILLIS")
251+
.build();
252+
QueryJobConfiguration job =
253+
QueryJobConfiguration.newBuilder(QUERY)
254+
.setQueryResultsFormat(format)
255+
.setArrowSerializationOptions(options)
256+
.build();
257+
258+
assertEquals(format, job.getQueryResultsFormat());
259+
assertEquals(options, job.getArrowSerializationOptions());
260+
261+
// Test toBuilder
262+
QueryJobConfiguration copiedJob = job.toBuilder().build();
263+
assertEquals(job, copiedJob);
264+
assertEquals(format, copiedJob.getQueryResultsFormat());
265+
assertEquals(options, copiedJob.getArrowSerializationOptions());
266+
267+
// Test toPb/fromPb (not preserved)
268+
QueryJobConfiguration jobFromPb = QueryJobConfiguration.fromPb(job.toPb());
269+
assertNull(jobFromPb.getQueryResultsFormat());
270+
assertNull(jobFromPb.getArrowSerializationOptions());
271+
}
272+
244273
private void compareQueryJobConfiguration(
245274
QueryJobConfiguration expected, QueryJobConfiguration value) {
246275
assertEquals(expected, value);

0 commit comments

Comments
 (0)