diff --git a/java-bigquery/README.md b/java-bigquery/README.md index 0305dd937b54..ce3126e9ae19 100644 --- a/java-bigquery/README.md +++ b/java-bigquery/README.md @@ -197,6 +197,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-bigquery/tree | 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) | | 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) | | 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) | +| 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) | | 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) | | 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) | | 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) | diff --git a/java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java b/java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java index 7ca564912c43..b5c278a0a146 100644 --- a/java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java +++ b/java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java @@ -1650,6 +1650,14 @@ TableResult query(QueryJobConfiguration configuration, JobId jobId, JobOption... *
Prerequisite: Requires the BigQuery Storage Read API ({@code * bigquerystorage.googleapis.com}) to be enabled on your GCP project. * + *
JVM Requirements (Java 16+): Apache Arrow uses internal {@code java.nio} + * DirectByteBuffer access for off-heap buffer management. Applications running on Java 16 or + * newer must supply the following JVM argument: + * + *
{@code
+ * --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
+ * }
+ *
* @param configuration the query configuration
* @param options query options
* @return an {@link ArrowQueryResult} streaming Arrow vectors
@@ -1675,6 +1683,14 @@ default ArrowQueryResult queryArrow(QueryJobConfiguration configuration, JobOpti
* Prerequisite: Requires the BigQuery Storage Read API ({@code * bigquerystorage.googleapis.com}) to be enabled on your GCP project. * + *
JVM Requirements (Java 16+): Apache Arrow uses internal {@code java.nio} + * DirectByteBuffer access for off-heap buffer management. Applications running on Java 16 or + * newer must supply the following JVM argument: + * + *
{@code
+ * --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
+ * }
+ *
* @param configuration the query configuration
* @param jobId the job ID to use
* @param options query options
diff --git a/java-bigquery/samples/snippets/src/main/java/com/example/bigquery/QueryArrow.java b/java-bigquery/samples/snippets/src/main/java/com/example/bigquery/QueryArrow.java
new file mode 100644
index 000000000000..b79508dd3363
--- /dev/null
+++ b/java-bigquery/samples/snippets/src/main/java/com/example/bigquery/QueryArrow.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2026 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.example.bigquery;
+
+// [START bigquery_query_arrow]
+
+import com.google.cloud.bigquery.ArrowQueryResult;
+import com.google.cloud.bigquery.BigQuery;
+import com.google.cloud.bigquery.BigQueryException;
+import com.google.cloud.bigquery.BigQueryOptions;
+import com.google.cloud.bigquery.QueryJobConfiguration;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.VectorSchemaRoot;
+
+public class QueryArrow {
+
+ public static void main(String[] args) {
+ // TODO(developer): Replace this query before running the sample.
+ String query =
+ "SELECT corpus, count(*) as corpus_count "
+ + "FROM `bigquery-public-data.samples.shakespeare` GROUP BY corpus;";
+ queryArrow(query);
+ }
+
+ /**
+ * Runs a query and streams Apache Arrow {@link VectorSchemaRoot} batches directly for zero-copy
+ * vector access.
+ *
+ * JVM Requirements (Java 16+): Applications running on Java 16 or newer must supply the + * following JVM option to allow Apache Arrow's memory allocator access to internal + * DirectByteBuffer: + * + *
{@code --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED}
+ */
+ public static void queryArrow(String query) {
+ try {
+ // Initialize client that will be used to send requests. This client only needs to be created
+ // once, and can be reused for multiple requests.
+ BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
+
+ // Create the query configuration.
+ QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query).build();
+
+ // Execute the query using queryArrow. Always close ArrowQueryResult to free off-heap memory.
+ try (ArrowQueryResult result = bigquery.queryArrow(queryConfig)) {
+ long totalRows = 0;
+ for (VectorSchemaRoot root : result) {
+ int rowCount = root.getRowCount();
+ totalRows += rowCount;
+ FieldVector corpusVector = root.getVector("corpus");
+ FieldVector countVector = root.getVector("corpus_count");
+
+ for (int i = 0; i < rowCount; i++) {
+ System.out.print("corpus:" + corpusVector.getObject(i));
+ System.out.print(", count:" + countVector.getObject(i));
+ System.out.println();
+ }
+ }
+ System.out.println("Arrow query ran successfully. Total rows: " + totalRows);
+ }
+ } catch (BigQueryException e) {
+ System.out.println("Arrow query did not run \n" + e.toString());
+ } catch (InterruptedException e) {
+ System.out.println("Arrow query was interrupted \n" + e.toString());
+ Thread.currentThread().interrupt();
+ }
+ }
+}
+// [END bigquery_query_arrow]
diff --git a/java-bigquery/samples/snippets/src/test/java/com/example/bigquery/QueryArrowIT.java b/java-bigquery/samples/snippets/src/test/java/com/example/bigquery/QueryArrowIT.java
new file mode 100644
index 000000000000..66e76d95f16d
--- /dev/null
+++ b/java-bigquery/samples/snippets/src/test/java/com/example/bigquery/QueryArrowIT.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2026 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.example.bigquery;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class QueryArrowIT {
+
+ private final Logger log = Logger.getLogger(this.getClass().getName());
+ private ByteArrayOutputStream bout;
+ private PrintStream out;
+ private PrintStream originalPrintStream;
+
+ @Before
+ public void setUp() {
+ bout = new ByteArrayOutputStream();
+ out = new PrintStream(bout);
+ originalPrintStream = System.out;
+ System.setOut(out);
+ }
+
+ @After
+ public void tearDown() {
+ // restores print statements in the original method
+ System.out.flush();
+ System.setOut(originalPrintStream);
+ log.log(Level.INFO, "\n" + bout.toString());
+ }
+
+ @Test
+ public void testQueryArrow() {
+ String query =
+ "SELECT corpus, count(*) as corpus_count "
+ + "FROM `bigquery-public-data.samples.shakespeare` GROUP BY corpus;";
+
+ QueryArrow.queryArrow(query);
+ assertThat(bout.toString()).contains("Arrow query ran successfully");
+ }
+}