Skip to content

Commit bd363f6

Browse files
authored
docs(bigquery): add QueryArrow code sample and document JDK 17+ JVM requirements (#14437)
Adds a QueryArrow code sample demonstrating zero-copy VectorSchemaRoot streaming with try-with-resources. Also documents the required --add-opens JVM flag in queryArrow Javadoc for applications running on JDK 17+.
1 parent 8f85c6e commit bd363f6

4 files changed

Lines changed: 161 additions & 0 deletions

File tree

java-bigquery/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-bigquery/tree
197197
| Load Partitioned Table | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/LoadPartitionedTable.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-bigquery&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/bigquery/LoadPartitionedTable.java) |
198198
| Load Table Clustered | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/LoadTableClustered.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-bigquery&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/bigquery/LoadTableClustered.java) |
199199
| Nested Repeated Schema | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/NestedRepeatedSchema.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-bigquery&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/bigquery/NestedRepeatedSchema.java) |
200+
| Query Arrow | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/QueryArrow.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-bigquery&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/bigquery/QueryArrow.java) |
200201
| Query Batch | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/QueryBatch.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-bigquery&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/bigquery/QueryBatch.java) |
201202
| Query Clustered Table | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/QueryClusteredTable.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-bigquery&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/bigquery/QueryClusteredTable.java) |
202203
| Query Destination Table Cmek | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/QueryDestinationTableCmek.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-bigquery&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/bigquery/QueryDestinationTableCmek.java) |

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,14 @@ TableResult query(QueryJobConfiguration configuration, JobId jobId, JobOption...
16501650
* <p><b>Prerequisite:</b> Requires the BigQuery Storage Read API ({@code
16511651
* bigquerystorage.googleapis.com}) to be enabled on your GCP project.
16521652
*
1653+
* <p><b>JVM Requirements (Java 16+):</b> Apache Arrow uses internal {@code java.nio}
1654+
* DirectByteBuffer access for off-heap buffer management. Applications running on Java 16 or
1655+
* newer must supply the following JVM argument:
1656+
*
1657+
* <pre>{@code
1658+
* --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
1659+
* }</pre>
1660+
*
16531661
* @param configuration the query configuration
16541662
* @param options query options
16551663
* @return an {@link ArrowQueryResult} streaming Arrow vectors
@@ -1675,6 +1683,14 @@ default ArrowQueryResult queryArrow(QueryJobConfiguration configuration, JobOpti
16751683
* <p><b>Prerequisite:</b> Requires the BigQuery Storage Read API ({@code
16761684
* bigquerystorage.googleapis.com}) to be enabled on your GCP project.
16771685
*
1686+
* <p><b>JVM Requirements (Java 16+):</b> Apache Arrow uses internal {@code java.nio}
1687+
* DirectByteBuffer access for off-heap buffer management. Applications running on Java 16 or
1688+
* newer must supply the following JVM argument:
1689+
*
1690+
* <pre>{@code
1691+
* --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
1692+
* }</pre>
1693+
*
16781694
* @param configuration the query configuration
16791695
* @param jobId the job ID to use
16801696
* @param options query options
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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.example.bigquery;
18+
19+
// [START bigquery_query_arrow]
20+
21+
import com.google.cloud.bigquery.ArrowQueryResult;
22+
import com.google.cloud.bigquery.BigQuery;
23+
import com.google.cloud.bigquery.BigQueryException;
24+
import com.google.cloud.bigquery.BigQueryOptions;
25+
import com.google.cloud.bigquery.QueryJobConfiguration;
26+
import org.apache.arrow.vector.FieldVector;
27+
import org.apache.arrow.vector.VectorSchemaRoot;
28+
29+
public class QueryArrow {
30+
31+
public static void main(String[] args) {
32+
// TODO(developer): Replace this query before running the sample.
33+
String query =
34+
"SELECT corpus, count(*) as corpus_count "
35+
+ "FROM `bigquery-public-data.samples.shakespeare` GROUP BY corpus;";
36+
queryArrow(query);
37+
}
38+
39+
/**
40+
* Runs a query and streams Apache Arrow {@link VectorSchemaRoot} batches directly for zero-copy
41+
* vector access.
42+
*
43+
* <p><b>JVM Requirements (Java 16+):</b> Applications running on Java 16 or newer must supply the
44+
* following JVM option to allow Apache Arrow's memory allocator access to internal
45+
* DirectByteBuffer:
46+
*
47+
* <pre>{@code --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED}</pre>
48+
*/
49+
public static void queryArrow(String query) {
50+
try {
51+
// Initialize client that will be used to send requests. This client only needs to be created
52+
// once, and can be reused for multiple requests.
53+
BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
54+
55+
// Create the query configuration.
56+
QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query).build();
57+
58+
// Execute the query using queryArrow. Always close ArrowQueryResult to free off-heap memory.
59+
try (ArrowQueryResult result = bigquery.queryArrow(queryConfig)) {
60+
long totalRows = 0;
61+
for (VectorSchemaRoot root : result) {
62+
int rowCount = root.getRowCount();
63+
totalRows += rowCount;
64+
FieldVector corpusVector = root.getVector("corpus");
65+
FieldVector countVector = root.getVector("corpus_count");
66+
67+
for (int i = 0; i < rowCount; i++) {
68+
System.out.print("corpus:" + corpusVector.getObject(i));
69+
System.out.print(", count:" + countVector.getObject(i));
70+
System.out.println();
71+
}
72+
}
73+
System.out.println("Arrow query ran successfully. Total rows: " + totalRows);
74+
}
75+
} catch (BigQueryException e) {
76+
System.out.println("Arrow query did not run \n" + e.toString());
77+
} catch (InterruptedException e) {
78+
System.out.println("Arrow query was interrupted \n" + e.toString());
79+
Thread.currentThread().interrupt();
80+
}
81+
}
82+
}
83+
// [END bigquery_query_arrow]
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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.example.bigquery;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
21+
import java.io.ByteArrayOutputStream;
22+
import java.io.PrintStream;
23+
import java.util.logging.Level;
24+
import java.util.logging.Logger;
25+
import org.junit.After;
26+
import org.junit.Before;
27+
import org.junit.Test;
28+
29+
public class QueryArrowIT {
30+
31+
private final Logger log = Logger.getLogger(this.getClass().getName());
32+
private ByteArrayOutputStream bout;
33+
private PrintStream out;
34+
private PrintStream originalPrintStream;
35+
36+
@Before
37+
public void setUp() {
38+
bout = new ByteArrayOutputStream();
39+
out = new PrintStream(bout);
40+
originalPrintStream = System.out;
41+
System.setOut(out);
42+
}
43+
44+
@After
45+
public void tearDown() {
46+
// restores print statements in the original method
47+
System.out.flush();
48+
System.setOut(originalPrintStream);
49+
log.log(Level.INFO, "\n" + bout.toString());
50+
}
51+
52+
@Test
53+
public void testQueryArrow() {
54+
String query =
55+
"SELECT corpus, count(*) as corpus_count "
56+
+ "FROM `bigquery-public-data.samples.shakespeare` GROUP BY corpus;";
57+
58+
QueryArrow.queryArrow(query);
59+
assertThat(bout.toString()).contains("Arrow query ran successfully");
60+
}
61+
}

0 commit comments

Comments
 (0)