diff --git a/README.md b/README.md index e61c8713d..9ec60a4f3 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-bigquery/tree | Sample | Source Code | Try it | | --------------------------- | --------------------------------- | ------ | +| Native Image Bigquery Sample | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/native-image-sample/src/main/java/com/example/bigquery/NativeImageBigquerySample.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/native-image-sample/src/main/java/com/example/bigquery/NativeImageBigquerySample.java) | | Add Column Load Append | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/AddColumnLoadAppend.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/AddColumnLoadAppend.java) | | Add Empty Column | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/AddEmptyColumn.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/AddEmptyColumn.java) | | Auth Drive Scope | [source code](https://github.com/googleapis/java-bigquery/blob/main/samples/snippets/src/main/java/com/example/bigquery/AuthDriveScope.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/AuthDriveScope.java) | diff --git a/samples/native-image-sample/README.md b/samples/native-image-sample/README.md new file mode 100644 index 000000000..e4e4b52ee --- /dev/null +++ b/samples/native-image-sample/README.md @@ -0,0 +1,47 @@ +# BigQuery Sample Application with Native Image + +The BigQuery sample application demonstrates some common operations with [Google Cloud BigQuery](https://cloud.google.com/bigquery) and is compatible with Native Image compilation. + +## Setup Instructions + +1. Follow the [GCP Project Authentication and Native Image Setup Instructions](../../README.md). + +2. [Enable the BigQuery APIs](https://console.cloud.google.com/apis/api/bigquery.googleapis.com). + +### Run with Native Image Support + +Navigate to this directory in a new terminal. + +1. Compile the application using the Native Image Compiler. This step may take a few minutes. + + ``` + mvn package -P native -DskipTests + ``` + +2. Run the application: + + ``` + ./target/native-image-sample + ``` + +3. The application will create a sample BigQuery dataset in your GCP project called `nativeimage_test_dataset` and perform some simple operations like creating a table, inserting data, and running a query. + + If you would like to delete the BigQuery dataset later, you can manage your BigQuery resources through [Google Cloud Console](https://console.cloud.google.com/bigquery) to clean up BigQuery resources under your project. + + When you run the application, you'll see output like this in the terminal: + + ``` + Created new table: nativeimage_test_table_2351b0891d2f48af9309bd289c3bad13 + Successfully inserted test row. + Queried the following records: + User id: TestUser-2f39e3ec-d81a-483f-9ec0-b9bd54155710 | age: 40 + Deleted table: nativeimage_test_table_2351b0891d2f48af9309bd289c3bad13 + ``` + +### Sample Integration test with Native Image Support + +In order to run the sample integration test, call the following command: + +``` +mvn test -Pnative +``` \ No newline at end of file diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml new file mode 100644 index 000000000..225e3ea20 --- /dev/null +++ b/samples/native-image-sample/pom.xml @@ -0,0 +1,161 @@ + + + + 4.0.0 + com.example.bigquery + native-image-sample + Native Image Sample + + + com.google.cloud.samples + shared-configuration + 1.2.0 + + + + 1.8 + 1.8 + UTF-8 + + + + + + com.google.cloud + libraries-bom + 24.2.0 + pom + import + + + + + + + com.google.cloud + google-cloud-bigquery + + + + + junit + junit + 4.13.2 + test + + + com.google.truth + truth + 1.1.3 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.example.bigquery.NativeImageBigquerySample + + + + + + + + + + + + native + + + + com.google.cloud + native-image-support + 0.10.0 + + + org.junit.vintage + junit-vintage-engine + 5.8.2 + test + + + org.graalvm.buildtools + junit-platform-native + 0.9.9 + test + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 2.22.2 + + + **/*IT + + + + + org.graalvm.buildtools + native-maven-plugin + 0.9.9 + true + + com.example.bigquery.NativeImageBigquerySample + + + --no-fallback + --no-server + + + + + build-native + + build + test + + package + + + test-native + + test + + test + + + + + + + + diff --git a/samples/native-image-sample/src/main/java/com/example/bigquery/NativeImageBigquerySample.java b/samples/native-image-sample/src/main/java/com/example/bigquery/NativeImageBigquerySample.java new file mode 100644 index 000000000..e7f1b35c5 --- /dev/null +++ b/samples/native-image-sample/src/main/java/com/example/bigquery/NativeImageBigquerySample.java @@ -0,0 +1,170 @@ +/* + * Copyright 2022 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 com.google.api.gax.paging.Page; +import com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryError; +import com.google.cloud.bigquery.BigQueryOptions; +import com.google.cloud.bigquery.Dataset; +import com.google.cloud.bigquery.DatasetInfo; +import com.google.cloud.bigquery.Field; +import com.google.cloud.bigquery.FieldValueList; +import com.google.cloud.bigquery.InsertAllRequest; +import com.google.cloud.bigquery.InsertAllResponse; +import com.google.cloud.bigquery.QueryJobConfiguration; +import com.google.cloud.bigquery.Schema; +import com.google.cloud.bigquery.StandardSQLTypeName; +import com.google.cloud.bigquery.StandardTableDefinition; +import com.google.cloud.bigquery.Table; +import com.google.cloud.bigquery.TableDefinition; +import com.google.cloud.bigquery.TableId; +import com.google.cloud.bigquery.TableInfo; +import com.google.cloud.bigquery.TableResult; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * Sample application demonstrating BigQuery operations. + * + *

Note: This application will create a BigQuery dataset in your GCP project. You can delete this + * by viewing BigQuery in Cloud Console https://console.cloud.google.com/bigquery or by uncommenting + * the call to `deleteDataset(..)` made in main(). + */ +public class NativeImageBigquerySample { + + private static final String DATASET_ID = "nativeimage_test_dataset"; + + private static final String TABLE_ID = "nativeimage_test_table"; + + private static final Schema TABLE_SCHEMA = + Schema.of( + Field.of("id", StandardSQLTypeName.STRING), Field.of("age", StandardSQLTypeName.INT64)); + + /** Entrypoint to the application. */ + public static void main(String[] args) throws InterruptedException { + BigQuery bigQuery = BigQueryOptions.getDefaultInstance().getService(); + + if (!hasDataset(bigQuery, DATASET_ID)) { + createDataset(bigQuery, DATASET_ID); + } + + String tableName = TABLE_ID + "_" + UUID.randomUUID().toString().replace("-", ""); + createTable(bigQuery, DATASET_ID, tableName, TABLE_SCHEMA); + String testId = "TestUser-" + UUID.randomUUID().toString(); + int testAge = 40; + insertTestRecord(bigQuery, DATASET_ID, tableName, testId, testAge); + queryTable(bigQuery, DATASET_ID, tableName); + + // Clean up resources. + deleteTable(bigQuery, DATASET_ID, tableName); + + // Uncomment this to delete the created dataset. + // deleteDataset(bigQuery, DATASET_ID); + } + + static String queryTable(BigQuery bigQuery, String datasetName, String tableName) + throws InterruptedException { + String fullyQualifiedTable = datasetName + "." + tableName; + String query = "SELECT * FROM " + fullyQualifiedTable; + + QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query).build(); + TableResult results = bigQuery.query(queryConfig); + + String result = ""; + System.out.println("Queried the following records: "); + for (FieldValueList row : results.iterateAll()) { + String rowStatement = + String.format( + "User id: %s | age: %d\n", + row.get("id").getStringValue(), row.get("age").getLongValue()); + result += rowStatement; + System.out.println(row); + } + return result; + } + + static void insertTestRecord( + BigQuery bigQuery, String datasetName, String tableName, String id, int age) { + + Map rowContent = new HashMap<>(); + rowContent.put("id", id); + rowContent.put("age", age); + + InsertAllRequest request = + InsertAllRequest.newBuilder(datasetName, tableName).addRow(rowContent).build(); + + InsertAllResponse response = bigQuery.insertAll(request); + + if (response.hasErrors()) { + System.out.println("Insert resulted in errors:"); + for (Map.Entry> entry : response.getInsertErrors().entrySet()) { + System.out.println("Response error: \n" + entry.getValue()); + } + } else { + System.out.println("Successfully inserted test row."); + } + } + + static void createTable(BigQuery bigQuery, String datasetName, String tableName, Schema schema) { + + TableId tableId = TableId.of(datasetName, tableName); + TableDefinition tableDefinition = StandardTableDefinition.of(schema); + TableInfo tableInfo = TableInfo.newBuilder(tableId, tableDefinition).build(); + bigQuery.create(tableInfo); + System.out.println("Created new table: " + tableName); + } + + static boolean hasTable(BigQuery bigQuery, String datasetName, String tableName) { + + Page tables = bigQuery.listTables(datasetName); + for (Table table : tables.iterateAll()) { + if (tableName.equals(table.getTableId().getTable())) { + return true; + } + } + return false; + } + + static void createDataset(BigQuery bigQuery, String datasetName) { + DatasetInfo datasetInfo = DatasetInfo.newBuilder(datasetName).build(); + Dataset newDataset = bigQuery.create(datasetInfo); + System.out.println("Created new dataset: " + newDataset.getDatasetId().getDataset()); + } + + static boolean hasDataset(BigQuery bigQuery, String datasetName) { + Page datasets = bigQuery.listDatasets(); + for (Dataset dataset : datasets.iterateAll()) { + if (datasetName.equals(dataset.getDatasetId().getDataset())) { + return true; + } + } + return false; + } + + static void deleteTable(BigQuery bigQuery, String datasetName, String tableName) { + bigQuery.getTable(datasetName, tableName).delete(); + System.out.println("Deleted table: " + tableName); + } + + static void deleteDataset(BigQuery bigQuery, String datasetName) { + bigQuery.getDataset(datasetName).delete(); + System.out.println("Deleting dataset " + datasetName); + } +} diff --git a/samples/native-image-sample/src/test/java/com/example/bigquery/NativeImageBigquerySampleIT.java b/samples/native-image-sample/src/test/java/com/example/bigquery/NativeImageBigquerySampleIT.java new file mode 100644 index 000000000..a65bc5aa8 --- /dev/null +++ b/samples/native-image-sample/src/test/java/com/example/bigquery/NativeImageBigquerySampleIT.java @@ -0,0 +1,67 @@ +/* + * Copyright 2022 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 com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryOptions; +import com.google.cloud.bigquery.Field; +import com.google.cloud.bigquery.Schema; +import com.google.cloud.bigquery.StandardSQLTypeName; +import java.util.UUID; +import org.junit.Before; +import org.junit.Test; + +/** Tests for {@link NativeImageBigquerySample} */ +public class NativeImageBigquerySampleIT { + + private static final String DATASET_ID = "nativeimage_it_dataset"; + + private static final String TABLE_ID = "nativeimage_it_table"; + + private static final Schema TABLE_SCHEMA = + Schema.of( + Field.of("id", StandardSQLTypeName.STRING), Field.of("age", StandardSQLTypeName.INT64)); + + private BigQuery bigQuery; + + private String tableName; + + @Before + public void setUp() { + bigQuery = BigQueryOptions.getDefaultInstance().getService(); + tableName = TABLE_ID + "_" + UUID.randomUUID().toString().replace("-", ""); + if (!NativeImageBigquerySample.hasDataset(bigQuery, DATASET_ID)) { + NativeImageBigquerySample.createDataset(bigQuery, DATASET_ID); + } + NativeImageBigquerySample.createTable(bigQuery, DATASET_ID, tableName, TABLE_SCHEMA); + } + + @Test + public void testQueryTable() throws InterruptedException { + String testId = "TestUser-" + UUID.randomUUID(); + NativeImageBigquerySample.insertTestRecord(bigQuery, DATASET_ID, tableName, testId, 40); + + String result = NativeImageBigquerySample.queryTable(bigQuery, DATASET_ID, tableName); + + assertThat(result).isEqualTo("User id: " + testId + " | age: 40\n"); + + // Clean up + NativeImageBigquerySample.deleteTable(bigQuery, DATASET_ID, tableName); + } +} diff --git a/samples/pom.xml b/samples/pom.xml index 4e9299af4..a02b0b6c4 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -47,6 +47,7 @@ install-without-bom snapshot snippets + native-image-sample