From 6ba2126da9c80b14f32123c98247f7e2332b1ada Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 17:56:27 -0400 Subject: [PATCH 01/16] chore(main): release 2.52.1-SNAPSHOT (#3864) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- benchmark/pom.xml | 2 +- google-cloud-bigquery-bom/pom.xml | 4 ++-- google-cloud-bigquery/pom.xml | 4 ++-- pom.xml | 4 ++-- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index bb58ca1e1..8fcf7ca00 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -6,7 +6,7 @@ google-cloud-bigquery-parent com.google.cloud - 2.52.0 + 2.52.1-SNAPSHOT diff --git a/google-cloud-bigquery-bom/pom.xml b/google-cloud-bigquery-bom/pom.xml index 836073eb4..1194e1b0e 100644 --- a/google-cloud-bigquery-bom/pom.xml +++ b/google-cloud-bigquery-bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-bigquery-bom - 2.52.0 + 2.52.1-SNAPSHOT pom com.google.cloud @@ -54,7 +54,7 @@ com.google.cloud google-cloud-bigquery - 2.52.0 + 2.52.1-SNAPSHOT diff --git a/google-cloud-bigquery/pom.xml b/google-cloud-bigquery/pom.xml index 644fe0ef5..6c7e1aed1 100644 --- a/google-cloud-bigquery/pom.xml +++ b/google-cloud-bigquery/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-bigquery - 2.52.0 + 2.52.1-SNAPSHOT jar BigQuery https://github.com/googleapis/java-bigquery @@ -11,7 +11,7 @@ com.google.cloud google-cloud-bigquery-parent - 2.52.0 + 2.52.1-SNAPSHOT google-cloud-bigquery diff --git a/pom.xml b/pom.xml index b265c66e3..6d9674e6f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-bigquery-parent pom - 2.52.0 + 2.52.1-SNAPSHOT BigQuery Parent https://github.com/googleapis/java-bigquery @@ -93,7 +93,7 @@ com.google.cloud google-cloud-bigquery - 2.52.0 + 2.52.1-SNAPSHOT diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 1a1655234..9e5136361 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -44,7 +44,7 @@ com.google.cloud google-cloud-bigquery - 2.52.0 + 2.52.1-SNAPSHOT diff --git a/versions.txt b/versions.txt index 2b5922874..5e931b82a 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-bigquery:2.52.0:2.52.0 \ No newline at end of file +google-cloud-bigquery:2.52.0:2.52.1-SNAPSHOT \ No newline at end of file From e2d23c1b15f2c48a4113f82b920f5c29c4b5dfea Mon Sep 17 00:00:00 2001 From: Liam Huffman <44932470+whuffman36@users.noreply.github.com> Date: Wed, 25 Jun 2025 23:14:57 -0700 Subject: [PATCH 02/16] feat(bigquery): Add OpenTelemetry support to BQ rpcs (#3860) * feat(bigquery): Add OpenTelemetry support to BQ rpcs * remove oauth and access token attributes * Capture repsponse ids in attributes * Fix attribute name scoping typos --- .../bigquery/spi/v2/HttpBigQueryRpc.java | 1062 ++++++++++++++--- .../cloud/bigquery/it/ITBigQueryTest.java | 20 + 2 files changed, 914 insertions(+), 168 deletions(-) diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java index 03e1fb586..9d89435ea 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/HttpBigQueryRpc.java @@ -69,6 +69,9 @@ import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; import java.io.IOException; import java.math.BigInteger; import java.util.List; @@ -155,7 +158,28 @@ public Dataset getDatasetSkipExceptionTranslation( if (options.containsKey(Option.DATASET_VIEW)) { bqGetRequest.setDatasetView(options.get(Option.DATASET_VIEW).toString()); } - return bqGetRequest.execute(); + + Span getDataset = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getDataset = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getDataset") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "GetDataset") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + + Dataset dataset = bqGetRequest.execute(); + if (getDataset != null) { + getDataset.setAttribute("bq.rpc.response.dataset.id", dataset.getId()); + getDataset.end(); + } + return dataset; } @Override @@ -171,7 +195,7 @@ public Tuple> listDatasets(String projectId, Map> listDatasetsSkipExceptionTranslation( String projectId, Map options) throws IOException { validateRPC(); - DatasetList datasetsList = + Bigquery.Datasets.List datasetsListRequest = bigquery .datasets() .list(projectId) @@ -179,9 +203,30 @@ public Tuple> listDatasetsSkipExceptionTranslation( .setAll(Option.ALL_DATASETS.getBoolean(options)) .setFilter(Option.LABEL_FILTER.getString(options)) .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .execute(); + .setPageToken(Option.PAGE_TOKEN.getString(options)); + + Span listDatasets = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listDatasets = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listDatasets") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "ListDatasets") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", datasetsListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + + DatasetList datasetsList = datasetsListRequest.execute(); Iterable datasets = datasetsList.getDatasets(); + if (listDatasets != null) { + listDatasets.setAttribute("bq.rpc.next_page_token", datasetsList.getNextPageToken()); + listDatasets.end(); + } return Tuple.of( datasetsList.getNextPageToken(), Iterables.transform( @@ -211,7 +256,27 @@ public Dataset createSkipExceptionTranslation(Dataset dataset, Map op if (options.containsKey(Option.ACCESS_POLICY_VERSION)) { bqCreateRequest.setAccessPolicyVersion((Integer) options.get(Option.ACCESS_POLICY_VERSION)); } - return bqCreateRequest.execute(); + + Span createDataset = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createDataset = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createDataset") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "InsertDataset") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Dataset datasetResponse = bqCreateRequest.execute(); + if (createDataset != null) { + createDataset.setAttribute("bq.rpc.response.dataset.id", datasetResponse.getId()); + createDataset.end(); + } + return datasetResponse; } @Override @@ -230,12 +295,33 @@ public Table createSkipExceptionTranslation(Table table, Map options) // unset the type, as it is output only table.setType(null); TableReference reference = table.getTableReference(); - return bigquery - .tables() - .insert(reference.getProjectId(), reference.getDatasetId(), table) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Tables.Insert bqCreateRequest = + bigquery + .tables() + .insert(reference.getProjectId(), reference.getDatasetId(), table) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + Span createTable = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createTable = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createTable") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "InsertTable") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Table tableResponse = bqCreateRequest.execute(); + if (createTable != null) { + createTable.setAttribute("bq.rpc.response.table.id", tableResponse.getId()); + createTable.end(); + } + return tableResponse; } @Override @@ -252,12 +338,34 @@ public Routine createSkipExceptionTranslation(Routine routine, Map op throws IOException { validateRPC(); RoutineReference reference = routine.getRoutineReference(); - return bigquery - .routines() - .insert(reference.getProjectId(), reference.getDatasetId(), routine) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Routines.Insert bqCreateRequest = + bigquery + .routines() + .insert(reference.getProjectId(), reference.getDatasetId(), routine) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + Span createRoutine = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createRoutine = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createRoutine") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "InsertRoutine") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Routine routineResponse = bqCreateRequest.execute(); + if (createRoutine != null) { + createRoutine.setAttribute( + "bq.rpc.response.routine.id", routineResponse.getRoutineReference().getRoutineId()); + createRoutine.end(); + } + return routineResponse; } @Override @@ -276,12 +384,35 @@ public Job createSkipExceptionTranslation(Job job, Map options) throw job.getJobReference() != null ? job.getJobReference().getProjectId() : this.options.getProjectId(); - return bigquery - .jobs() - .insert(projectId, job) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Jobs.Insert bqCreateRequest = + bigquery + .jobs() + .insert(projectId, job) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + Span createJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "InsertJob") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Job jobResponse = bqCreateRequest.execute(); + if (createJob != null) { + createJob.setAttribute("bq.rpc.response.job.id", jobResponse.getId()); + createJob.setAttribute( + "bq.rpc.response.job.status.state", jobResponse.getStatus().getState()); + createJob.end(); + } + return jobResponse; } @Override @@ -300,7 +431,30 @@ public Job createJobForQuerySkipExceptionTranslation(Job job) throws IOException job.getJobReference() != null ? job.getJobReference().getProjectId() : this.options.getProjectId(); - return bigquery.jobs().insert(projectId, job).setPrettyPrint(false).execute(); + Bigquery.Jobs.Insert bqCreateRequest = + bigquery.jobs().insert(projectId, job).setPrettyPrint(false); + + Span createJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + createJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.createJobForQuery") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "InsertJob") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + Job jobResponse = bqCreateRequest.execute(); + if (createJob != null) { + createJob.setAttribute("bq.rpc.response.job.id", jobResponse.getId()); + createJob.setAttribute( + "bq.rpc.response.job.status.state", jobResponse.getStatus().getState()); + createJob.end(); + } + return jobResponse; } @Override @@ -320,12 +474,31 @@ public boolean deleteDataset(String projectId, String datasetId, Map public boolean deleteDatasetSkipExceptionTranslation( String projectId, String datasetId, Map options) throws IOException { validateRPC(); - bigquery - .datasets() - .delete(projectId, datasetId) - .setPrettyPrint(false) - .setDeleteContents(Option.DELETE_CONTENTS.getBoolean(options)) - .execute(); + Bigquery.Datasets.Delete bqDeleteRequest = + bigquery + .datasets() + .delete(projectId, datasetId) + .setPrettyPrint(false) + .setDeleteContents(Option.DELETE_CONTENTS.getBoolean(options)); + + Span deleteDataset = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteDataset = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.deleteDataset") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "DeleteDataset") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteDataset != null) { + deleteDataset.end(); + } return true; } @@ -355,7 +528,27 @@ public Dataset patchSkipExceptionTranslation(Dataset dataset, Map opt if (options.containsKey(Option.DATASET_UPDATE_MODE)) { bqPatchRequest.setUpdateMode(options.get(Option.DATASET_UPDATE_MODE).toString()); } - return bqPatchRequest.execute(); + + Span patchDataset = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + patchDataset = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.patchDataset") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "DatasetService") + .setAttribute("bq.rpc.method", "PatchDataset") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Dataset datasetResponse = bqPatchRequest.execute(); + if (patchDataset != null) { + patchDataset.setAttribute("bq.rpc.response.dataset.id", datasetResponse.getId()); + patchDataset.end(); + } + return datasetResponse; } @Override @@ -374,13 +567,35 @@ public Table patchSkipExceptionTranslation(Table table, Map options) // unset the type, as it is output only table.setType(null); TableReference reference = table.getTableReference(); - return bigquery - .tables() - .patch(reference.getProjectId(), reference.getDatasetId(), reference.getTableId(), table) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .setAutodetectSchema(BigQueryRpc.Option.AUTODETECT_SCHEMA.getBoolean(options)) - .execute(); + Bigquery.Tables.Patch bqPatchRequest = + bigquery + .tables() + .patch( + reference.getProjectId(), reference.getDatasetId(), reference.getTableId(), table) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)) + .setAutodetectSchema(BigQueryRpc.Option.AUTODETECT_SCHEMA.getBoolean(options)); + + Span patchTable = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + patchTable = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.patchTable") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "PatchTable") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Table tableResponse = bqPatchRequest.execute(); + if (patchTable != null) { + patchTable.setAttribute("bq.rpc.response.table.id", tableResponse.getId()); + patchTable.end(); + } + return tableResponse; } @Override @@ -402,13 +617,34 @@ public Table getTableSkipExceptionTranslation( String projectId, String datasetId, String tableId, Map options) throws IOException { validateRPC(); - return bigquery - .tables() - .get(projectId, datasetId, tableId) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .setView(getTableMetadataOption(options)) - .execute(); + Bigquery.Tables.Get bqGetRequest = + bigquery + .tables() + .get(projectId, datasetId, tableId) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)) + .setView(getTableMetadataOption(options)); + + Span getTable = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getTable = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getTable") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "GetTable") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Table tableResponse = bqGetRequest.execute(); + if (getTable != null) { + getTable.setAttribute("bq.rpc.response.table.id", tableResponse.getId()); + getTable.end(); + } + return tableResponse; } private String getTableMetadataOption(Map options) { @@ -432,17 +668,38 @@ public Tuple> listTables( public Tuple> listTablesSkipExceptionTranslation( String projectId, String datasetId, Map options) throws IOException { validateRPC(); - TableList tableList = + Bigquery.Tables.List tableListRequest = bigquery .tables() .list(projectId, datasetId) .setPrettyPrint(false) .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .execute(); - Iterable tables = tableList.getTables(); + .setPageToken(Option.PAGE_TOKEN.getString(options)); + + Span listTables = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listTables = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listTables") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "ListTables") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", tableListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + TableList tableResponse = tableListRequest.execute(); + if (listTables != null) { + listTables.setAttribute("bq.rpc.next_page_token", tableResponse.getNextPageToken()); + listTables.end(); + } + + Iterable tables = tableResponse.getTables(); return Tuple.of( - tableList.getNextPageToken(), + tableResponse.getNextPageToken(), Iterables.transform( tables != null ? tables : ImmutableList.of(), new Function() { @@ -480,7 +737,26 @@ public boolean deleteTable(String projectId, String datasetId, String tableId) { public boolean deleteTableSkipExceptionTranslation( String projectId, String datasetId, String tableId) throws IOException { validateRPC(); - bigquery.tables().delete(projectId, datasetId, tableId).execute(); + Bigquery.Tables.Delete bqDeleteRequest = + bigquery.tables().delete(projectId, datasetId, tableId); + + Span deleteTable = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteTable = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.deleteTable") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableService") + .setAttribute("bq.rpc.method", "DeleteTable") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteTable != null) { + deleteTable.end(); + } return true; } @@ -499,12 +775,35 @@ public Model patchSkipExceptionTranslation(Model model, Map options) validateRPC(); // unset the type, as it is output only ModelReference reference = model.getModelReference(); - return bigquery - .models() - .patch(reference.getProjectId(), reference.getDatasetId(), reference.getModelId(), model) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Models.Patch bqPatchRequest = + bigquery + .models() + .patch( + reference.getProjectId(), reference.getDatasetId(), reference.getModelId(), model) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + Span patchModel = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + patchModel = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.patchModel") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "ModelService") + .setAttribute("bq.rpc.method", "PatchModel") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Model modelResponse = bqPatchRequest.execute(); + if (patchModel != null) { + patchModel.setAttribute( + "bq.rpc.response.model.id", modelResponse.getModelReference().getModelId()); + patchModel.end(); + } + return modelResponse; } @Override @@ -526,12 +825,34 @@ public Model getModelSkipExceptionTranslation( String projectId, String datasetId, String modelId, Map options) throws IOException { validateRPC(); - return bigquery - .models() - .get(projectId, datasetId, modelId) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Models.Get bqGetRequest = + bigquery + .models() + .get(projectId, datasetId, modelId) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + Span getModel = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getModel = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getModel") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "ModelService") + .setAttribute("bq.rpc.method", "GetModel") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Model modelResponse = bqGetRequest.execute(); + if (getModel != null) { + getModel.setAttribute( + "bq.rpc.response.model.id", modelResponse.getModelReference().getModelId()); + getModel.end(); + } + return modelResponse; } @Override @@ -548,17 +869,38 @@ public Tuple> listModels( public Tuple> listModelsSkipExceptionTranslation( String projectId, String datasetId, Map options) throws IOException { validateRPC(); - ListModelsResponse modelList = + Bigquery.Models.List modelListRequest = bigquery .models() .list(projectId, datasetId) .setPrettyPrint(false) .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .execute(); + .setPageToken(Option.PAGE_TOKEN.getString(options)); + + Span listModels = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listModels = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listModels") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "ModelService") + .setAttribute("bq.rpc.method", "ListModels") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", modelListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + ListModelsResponse modelResponse = modelListRequest.execute(); + if (listModels != null) { + listModels.setAttribute("bq.rpc.next_page_token", modelResponse.getNextPageToken()); + listModels.end(); + } + Iterable models = - modelList.getModels() != null ? modelList.getModels() : ImmutableList.of(); - return Tuple.of(modelList.getNextPageToken(), models); + modelResponse.getModels() != null ? modelResponse.getModels() : ImmutableList.of(); + return Tuple.of(modelResponse.getNextPageToken(), models); } @Override @@ -578,7 +920,26 @@ public boolean deleteModel(String projectId, String datasetId, String modelId) { public boolean deleteModelSkipExceptionTranslation( String projectId, String datasetId, String modelId) throws IOException { validateRPC(); - bigquery.models().delete(projectId, datasetId, modelId).execute(); + Bigquery.Models.Delete bqDeleteRequest = + bigquery.models().delete(projectId, datasetId, modelId); + + Span deleteModels = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteModels = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.deleteModel") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "ModelService") + .setAttribute("bq.rpc.method", "DeleteModel") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteModels != null) { + deleteModels.end(); + } return true; } @@ -596,13 +957,38 @@ public Routine updateSkipExceptionTranslation(Routine routine, Map op throws IOException { validateRPC(); RoutineReference reference = routine.getRoutineReference(); - return bigquery - .routines() - .update( - reference.getProjectId(), reference.getDatasetId(), reference.getRoutineId(), routine) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Routines.Update bqUpdateRequest = + bigquery + .routines() + .update( + reference.getProjectId(), + reference.getDatasetId(), + reference.getRoutineId(), + routine) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + Span updateRoutine = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + updateRoutine = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.updateRoutine") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "UpdateRoutine") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Routine routineResponse = bqUpdateRequest.execute(); + if (updateRoutine != null) { + updateRoutine.setAttribute( + "bq.rpc.response.routine.id", routineResponse.getRoutineReference().getRoutineId()); + updateRoutine.end(); + } + return routineResponse; } @Override @@ -624,12 +1010,34 @@ public Routine getRoutineSkipExceptionTranslation( String projectId, String datasetId, String routineId, Map options) throws IOException { validateRPC(); - return bigquery - .routines() - .get(projectId, datasetId, routineId) - .setPrettyPrint(false) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Routines.Get bqGetRequest = + bigquery + .routines() + .get(projectId, datasetId, routineId) + .setPrettyPrint(false) + .setFields(Option.FIELDS.getString(options)); + + Span getRoutine = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getRoutine = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getRoutine") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "GetRoutine") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Routine routineResponse = bqGetRequest.execute(); + if (getRoutine != null) { + getRoutine.setAttribute( + "bq.rpc.response.routine.id", routineResponse.getRoutineReference().getRoutineId()); + getRoutine.end(); + } + return routineResponse; } @Override @@ -646,17 +1054,39 @@ public Tuple> listRoutines( public Tuple> listRoutinesSkipExceptionTranslation( String projectId, String datasetId, Map options) throws IOException { validateRPC(); - ListRoutinesResponse routineList = + Bigquery.Routines.List routineListRequest = bigquery .routines() .list(projectId, datasetId) .setPrettyPrint(false) .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .execute(); + .setPageToken(Option.PAGE_TOKEN.getString(options)); + + Span listRoutines = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listRoutines = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listRoutines") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "ListRoutines") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", routineListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + ListRoutinesResponse routineResponse = routineListRequest.execute(); + if (listRoutines != null) { + listRoutines.setAttribute("bq.rpc.next_page_token", routineResponse.getNextPageToken()); + listRoutines.end(); + } Iterable routines = - routineList.getRoutines() != null ? routineList.getRoutines() : ImmutableList.of(); - return Tuple.of(routineList.getNextPageToken(), routines); + routineResponse.getRoutines() != null + ? routineResponse.getRoutines() + : ImmutableList.of(); + return Tuple.of(routineResponse.getNextPageToken(), routines); } @Override @@ -676,7 +1106,26 @@ public boolean deleteRoutine(String projectId, String datasetId, String routineI public boolean deleteRoutineSkipExceptionTranslation( String projectId, String datasetId, String routineId) throws IOException { validateRPC(); - bigquery.routines().delete(projectId, datasetId, routineId).execute(); + Bigquery.Routines.Delete bqDeleteRequest = + bigquery.routines().delete(projectId, datasetId, routineId); + + Span deleteRoutine = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteRoutine = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listRoutines") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "RoutineService") + .setAttribute("bq.rpc.method", "ListRoutines") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteRoutine != null) { + deleteRoutine.end(); + } return true; } @@ -695,11 +1144,30 @@ public TableDataInsertAllResponse insertAllSkipExceptionTranslation( String projectId, String datasetId, String tableId, TableDataInsertAllRequest request) throws IOException { validateRPC(); - return bigquery - .tabledata() - .insertAll(projectId, datasetId, tableId, request) - .setPrettyPrint(false) - .execute(); + Bigquery.Tabledata.InsertAll insertAllRequest = + bigquery + .tabledata() + .insertAll(projectId, datasetId, tableId, request) + .setPrettyPrint(false); + + Span insertAll = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + insertAll = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.insertAll") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableDataService") + .setAttribute("bq.rpc.method", "InsertAll") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + TableDataInsertAllResponse insertAllResponse = insertAllRequest.execute(); + if (insertAll != null) { + insertAll.end(); + } + return insertAllResponse; } @Override @@ -717,17 +1185,38 @@ public TableDataList listTableDataSkipExceptionTranslation( String projectId, String datasetId, String tableId, Map options) throws IOException { validateRPC(); - return bigquery - .tabledata() - .list(projectId, datasetId, tableId) - .setPrettyPrint(false) - .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .setStartIndex( - Option.START_INDEX.getLong(options) != null - ? BigInteger.valueOf(Option.START_INDEX.getLong(options)) - : null) - .execute(); + Bigquery.Tabledata.List bqListRequest = + bigquery + .tabledata() + .list(projectId, datasetId, tableId) + .setPrettyPrint(false) + .setMaxResults(Option.MAX_RESULTS.getLong(options)) + .setPageToken(Option.PAGE_TOKEN.getString(options)) + .setStartIndex( + Option.START_INDEX.getLong(options) != null + ? BigInteger.valueOf(Option.START_INDEX.getLong(options)) + : null); + + Span listTableData = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listTableData = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listTableData") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableDataService") + .setAttribute("bq.rpc.method", "List") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", bqListRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + TableDataList bqListResponse = bqListRequest.execute(); + if (listTableData != null) { + listTableData.end(); + } + return bqListResponse; } @Override @@ -754,13 +1243,33 @@ public TableDataList listTableDataWithRowLimitSkipExceptionTranslation( String pageToken) throws IOException { validateRPC(); - return bigquery - .tabledata() - .list(projectId, datasetId, tableId) - .setPrettyPrint(false) - .setMaxResults(Long.valueOf(maxResultPerPage)) - .setPageToken(pageToken) - .execute(); + Bigquery.Tabledata.List bqListRequest = + bigquery + .tabledata() + .list(projectId, datasetId, tableId) + .setPrettyPrint(false) + .setMaxResults(Long.valueOf(maxResultPerPage)) + .setPageToken(pageToken); + + Span listTableData = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listTableData = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listTableDataWithRowLimit") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "TableDataService") + .setAttribute("bq.rpc.method", "List") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", bqListRequest.getPageToken()) + .startSpan(); + } + TableDataList bqListResponse = bqListRequest.execute(); + if (listTableData != null) { + listTableData.end(); + } + return bqListResponse; } @Override @@ -780,13 +1289,35 @@ public Job getJob(String projectId, String jobId, String location, Map options) throws IOException { validateRPC(); - return bigquery - .jobs() - .get(projectId, jobId) - .setPrettyPrint(false) - .setLocation(location) - .setFields(Option.FIELDS.getString(options)) - .execute(); + Bigquery.Jobs.Get bqGetRequest = + bigquery + .jobs() + .get(projectId, jobId) + .setPrettyPrint(false) + .setLocation(location) + .setFields(Option.FIELDS.getString(options)); + + Span getJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "GetJob") + .setAttribute("bq.rpc.system", "http") + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + Job jobResponse = bqGetRequest.execute(); + if (getJob != null) { + getJob.setAttribute("bq.rpc.response.job.id", jobResponse.getId()); + getJob.setAttribute("bq.rpc.response.job.status.state", jobResponse.getStatus().getState()); + getJob.end(); + } + return jobResponse; } @Override @@ -806,12 +1337,29 @@ public Job getQueryJob(String projectId, String jobId, String location) { public Job getQueryJobSkipExceptionTranslation(String projectId, String jobId, String location) throws IOException { validateRPC(); - return bigquery - .jobs() - .get(projectId, jobId) - .setPrettyPrint(false) - .setLocation(location) - .execute(); + Bigquery.Jobs.Get bqGetRequest = + bigquery.jobs().get(projectId, jobId).setPrettyPrint(false).setLocation(location); + + Span getJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getQueryJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "GetJob") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + Job jobResponse = bqGetRequest.execute(); + if (getJob != null) { + getJob.setAttribute("bq.rpc.response.job.id", jobResponse.getId()); + getJob.setAttribute("bq.rpc.response.job.status.state", jobResponse.getStatus().getState()); + getJob.end(); + } + return jobResponse; } @Override @@ -845,7 +1393,27 @@ public Tuple> listJobsSkipExceptionTranslation( if (Option.MAX_CREATION_TIME.getLong(options) != null) { request.setMaxCreationTime(BigInteger.valueOf(Option.MAX_CREATION_TIME.getLong(options))); } + + Span listJobs = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + listJobs = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.listJobs") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "ListJobs") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", request.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } JobList jobsList = request.execute(); + if (listJobs != null) { + listJobs.setAttribute("bq.rpc.next_page_token", jobsList.getNextPageToken()); + listJobs.end(); + } Iterable jobs = jobsList.getJobs(); return Tuple.of( @@ -892,7 +1460,26 @@ public boolean cancel(String projectId, String jobId, String location) { public boolean cancelSkipExceptionTranslation(String projectId, String jobId, String location) throws IOException { validateRPC(); - bigquery.jobs().cancel(projectId, jobId).setLocation(location).setPrettyPrint(false).execute(); + Bigquery.Jobs.Cancel bqCancelRequest = + bigquery.jobs().cancel(projectId, jobId).setLocation(location).setPrettyPrint(false); + + Span cancelJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + cancelJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.cancelJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "CancelJob") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqCancelRequest.execute(); + if (cancelJob != null) { + cancelJob.end(); + } return true; } @@ -909,12 +1496,26 @@ public boolean deleteJob(String projectId, String jobName, String location) { public boolean deleteJobSkipExceptionTranslation( String projectId, String jobName, String location) throws IOException { validateRPC(); - bigquery - .jobs() - .delete(projectId, jobName) - .setLocation(location) - .setPrettyPrint(false) - .execute(); + Bigquery.Jobs.Delete bqDeleteRequest = + bigquery.jobs().delete(projectId, jobName).setLocation(location).setPrettyPrint(false); + + Span deleteJob = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + deleteJob = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.deleteJob") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "DeleteJob") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + bqDeleteRequest.execute(); + if (deleteJob != null) { + deleteJob.end(); + } return true; } @@ -932,19 +1533,41 @@ public GetQueryResultsResponse getQueryResults( public GetQueryResultsResponse getQueryResultsSkipExceptionTranslation( String projectId, String jobId, String location, Map options) throws IOException { validateRPC(); - return bigquery - .jobs() - .getQueryResults(projectId, jobId) - .setPrettyPrint(false) - .setLocation(location) - .setMaxResults(Option.MAX_RESULTS.getLong(options)) - .setPageToken(Option.PAGE_TOKEN.getString(options)) - .setStartIndex( - Option.START_INDEX.getLong(options) != null - ? BigInteger.valueOf(Option.START_INDEX.getLong(options)) - : null) - .setTimeoutMs(Option.TIMEOUT.getLong(options)) - .execute(); + Bigquery.Jobs.GetQueryResults queryRequest = + bigquery + .jobs() + .getQueryResults(projectId, jobId) + .setPrettyPrint(false) + .setLocation(location) + .setMaxResults(Option.MAX_RESULTS.getLong(options)) + .setPageToken(Option.PAGE_TOKEN.getString(options)) + .setStartIndex( + Option.START_INDEX.getLong(options) != null + ? BigInteger.valueOf(Option.START_INDEX.getLong(options)) + : null) + .setTimeoutMs(Option.TIMEOUT.getLong(options)); + + Span getQueryResults = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getQueryResults = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getQueryResults") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "GetQueryResults") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", queryRequest.getPageToken()) + .setAllAttributes(otelAttributesFromOptions(options)) + .startSpan(); + } + + GetQueryResultsResponse queryResponse = queryRequest.execute(); + if (getQueryResults != null) { + getQueryResults.end(); + } + return queryResponse; } @Override @@ -963,14 +1586,35 @@ public GetQueryResultsResponse getQueryResultsWithRowLimitSkipExceptionTranslati String projectId, String jobId, String location, Integer maxResultPerPage, Long timeoutMs) throws IOException { validateRPC(); - return bigquery - .jobs() - .getQueryResults(projectId, jobId) - .setPrettyPrint(false) - .setLocation(location) - .setMaxResults(Long.valueOf(maxResultPerPage)) - .setTimeoutMs(timeoutMs) - .execute(); + Bigquery.Jobs.GetQueryResults queryRequest = + bigquery + .jobs() + .getQueryResults(projectId, jobId) + .setPrettyPrint(false) + .setLocation(location) + .setMaxResults(Long.valueOf(maxResultPerPage)) + .setTimeoutMs(timeoutMs); + + Span getQueryResults = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getQueryResults = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.getQueryResultsWithRowLimit") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "GetQueryResults") + .setAttribute("bq.rpc.system", "http") + .setAttribute("bq.rpc.page_token", queryRequest.getPageToken()) + .startSpan(); + } + + GetQueryResultsResponse queryResponse = queryRequest.execute(); + if (getQueryResults != null) { + getQueryResults.end(); + } + return queryResponse; } @Override @@ -986,7 +1630,27 @@ public QueryResponse queryRpc(String projectId, QueryRequest content) { public QueryResponse queryRpcSkipExceptionTranslation(String projectId, QueryRequest content) throws IOException { validateRPC(); - return bigquery.jobs().query(projectId, content).execute(); + Bigquery.Jobs.Query queryRequest = bigquery.jobs().query(projectId, content); + + Span getQueryResults = null; + if (this.options.isOpenTelemetryTracingEnabled() + && this.options.getOpenTelemetryTracer() != null) { + getQueryResults = + this.options + .getOpenTelemetryTracer() + .spanBuilder("com.google.cloud.bigquery.BigQueryRpc.queryRpc") + .setSpanKind(SpanKind.CLIENT) + .setAttribute("bq.rpc.service", "JobService") + .setAttribute("bq.rpc.method", "Query") + .setAttribute("bq.rpc.system", "http") + .startSpan(); + } + + QueryResponse queryResponse = queryRequest.execute(); + if (getQueryResults != null) { + getQueryResults.end(); + } + return queryResponse; } @Override @@ -1098,11 +1762,29 @@ public Policy getIamPolicySkipExceptionTranslation(String resourceId, Map From e5467c917c63ac066edcbcd902cc2093a39971a3 Mon Sep 17 00:00:00 2001 From: Liam Huffman <44932470+whuffman36@users.noreply.github.com> Date: Mon, 30 Jun 2025 16:27:08 -0700 Subject: [PATCH 09/16] feat(bigquery): Add support for custom timezones and timestamps (#3859) * feat(bigquery): Add support for custom timezones and timestamps * update ignored-diff * fix data -> date typo * Add enums for SourceColumnMatch * Change null markers test names * change enums to StringEnumValue --- .../clirr-ignored-differences.xml | 70 ++++++ .../bigquery/ExternalTableDefinition.java | 186 +++++++++++++++ .../cloud/bigquery/LoadJobConfiguration.java | 219 +++++++++++++++++- .../bigquery/ExternalTableDefinitionTest.java | 29 +++ .../bigquery/LoadJobConfigurationTest.java | 22 ++ 5 files changed, 525 insertions(+), 1 deletion(-) diff --git a/google-cloud-bigquery/clirr-ignored-differences.xml b/google-cloud-bigquery/clirr-ignored-differences.xml index e048f4ce8..bd455d2d4 100644 --- a/google-cloud-bigquery/clirr-ignored-differences.xml +++ b/google-cloud-bigquery/clirr-ignored-differences.xml @@ -2,6 +2,76 @@ + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *TimeZone(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *DateFormat(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *DatetimeFormat(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *TimeFormat(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *TimestampFormat(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *SourceColumnMatch(*) + + + 7013 + com/google/cloud/bigquery/ExternalTableDefinition* + *NullMarkers(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *TimeZone(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *DateFormat(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *DatetimeFormat(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *TimeFormat(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *TimestampFormat(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *SourceColumnMatch(*) + + + 7013 + com/google/cloud/bigquery/LoadJobConfiguration* + *NullMarkers(*) + 7004 com/google/cloud/bigquery/BigQueryRetryHelper diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ExternalTableDefinition.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ExternalTableDefinition.java index ea4cceead..c1859c3f9 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ExternalTableDefinition.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ExternalTableDefinition.java @@ -19,9 +19,12 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Strings.isNullOrEmpty; +import com.google.api.core.ApiFunction; import com.google.api.services.bigquery.model.ExternalDataConfiguration; import com.google.api.services.bigquery.model.Table; import com.google.auto.value.AutoValue; +import com.google.cloud.StringEnumType; +import com.google.cloud.StringEnumValue; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import java.util.List; @@ -57,6 +60,46 @@ public ExternalDataConfiguration apply(ExternalTableDefinition tableInfo) { private static final long serialVersionUID = -5951580238459622025L; + public static final class SourceColumnMatch extends StringEnumValue { + private static final long serialVersionUID = 818920627219751207L; + private static final ApiFunction CONSTRUCTOR = + new ApiFunction() { + @Override + public SourceColumnMatch apply(String constant) { + return new SourceColumnMatch(constant); + } + }; + + private static final StringEnumType type = + new StringEnumType(SourceColumnMatch.class, CONSTRUCTOR); + + public static final SourceColumnMatch POSITION = type.createAndRegister("POSITION"); + + public static final SourceColumnMatch NAME = type.createAndRegister("NAME"); + + private SourceColumnMatch(String constant) { + super(constant); + } + + /** + * Get the SourceColumnMatch for the given String constant, and throw an exception if the + * constant is not recognized. + */ + public static SourceColumnMatch valueOfStrict(String constant) { + return type.valueOfStrict(constant); + } + + /** Get the SourceColumnMatch for the given String constant, and allow unrecognized values. */ + public static SourceColumnMatch valueOf(String constant) { + return type.valueOf(constant); + } + + /** Return the known values for SourceColumnMatch. */ + public static SourceColumnMatch[] values() { + return type.values(); + } + } + @AutoValue.Builder public abstract static class Builder extends TableDefinition.Builder { @@ -215,6 +258,45 @@ public Builder setMaxStaleness(String maxStaleness) { abstract Builder setMaxStalenessInner(String maxStaleness); + /** + * Time zone used when parsing timestamp values that do not have specific time zone information + * (e.g. 2024-04-20 12:34:56). The expected format is a IANA timezone string (e.g. + * America/Los_Angeles). + */ + public abstract Builder setTimeZone(String timeZone); + + /** Format used to parse DATE values. Supports C-style and SQL-style values. */ + public abstract Builder setDateFormat(String dateFormat); + + /** Format used to parse DATETIME values. Supports C-style and SQL-style values. */ + public abstract Builder setDatetimeFormat(String datetimeFormat); + + /** Format used to parse TIME values. Supports C-style and SQL-style values. */ + public abstract Builder setTimeFormat(String timeFormat); + + /** Format used to parse TIMESTAMP values. Supports C-style and SQL-style values. */ + public abstract Builder setTimestampFormat(String timestampFormat); + + /** + * Controls the strategy used to match loaded columns to the schema. If not set, a sensible + * default is chosen based on how the schema is provided. If autodetect is used, then columns + * are matched by name. Otherwise, columns are matched by position. This is done to keep the + * behavior backward-compatible. Acceptable values are: POSITION - matches by position. This + * assumes that the columns are ordered the same way as the schema. NAME - matches by name. This + * reads the header row as column names and reorders columns to match the field names in the + * schema. + */ + public abstract Builder setSourceColumnMatch(SourceColumnMatch sourceColumnMatch); + + /** + * A list of strings represented as SQL NULL value in a CSV file. null_marker and null_markers + * can't be set at the same time. If null_marker is set, null_markers has to be not set. If + * null_markers is set, null_marker has to be not set. If both null_marker and null_markers are + * set at the same time, a user error would be thrown. Any strings listed in null_markers, + * including empty string would be interpreted as SQL NULL. This applies to all column types. + */ + public abstract Builder setNullMarkers(List nullMarkers); + /** Creates an {@code ExternalTableDefinition} object. */ @Override public abstract ExternalTableDefinition build(); @@ -373,6 +455,37 @@ public HivePartitioningOptions getHivePartitioningOptions() { return getHivePartitioningOptionsInner(); } + /** + * Returns the time zone used when parsing timestamp values that don't have specific time zone + * information. + */ + @Nullable + public abstract String getTimeZone(); + + /** Returns the format used to parse DATE values. */ + @Nullable + public abstract String getDateFormat(); + + /** Returns the format used to parse DATETIME values. */ + @Nullable + public abstract String getDatetimeFormat(); + + /** Returns the format used to parse TIME values. */ + @Nullable + public abstract String getTimeFormat(); + + /** Returns the format used to parse TIMESTAMP values. */ + @Nullable + public abstract String getTimestampFormat(); + + /** Returns the strategy used to match loaded columns to the schema, either POSITION or NAME. */ + @Nullable + public abstract SourceColumnMatch getSourceColumnMatch(); + + /** Returns a list of strings represented as SQL NULL value in a CSV file. */ + @Nullable + public abstract List getNullMarkers(); + @Nullable abstract HivePartitioningOptions getHivePartitioningOptionsInner(); @@ -454,6 +567,29 @@ com.google.api.services.bigquery.model.ExternalDataConfiguration toExternalDataC if (getMetadataCacheMode() != null) { externalConfigurationPb.setMetadataCacheMode(getMetadataCacheMode()); } + if (getTimeZone() != null) { + externalConfigurationPb.setTimeZone(getTimeZone()); + } + if (getDateFormat() != null) { + externalConfigurationPb.setDateFormat(getDateFormat()); + } + if (getDatetimeFormat() != null) { + externalConfigurationPb.setDatetimeFormat(getDatetimeFormat()); + } + if (getTimeFormat() != null) { + externalConfigurationPb.setTimeFormat(getTimeFormat()); + } + if (getTimestampFormat() != null) { + externalConfigurationPb.setTimestampFormat(getTimestampFormat()); + } + if (getSourceColumnMatch() != null) { + externalConfigurationPb + .getCsvOptions() + .setSourceColumnMatch(getSourceColumnMatch().toString()); + } + if (getNullMarkers() != null) { + externalConfigurationPb.getCsvOptions().setNullMarkers(getNullMarkers()); + } return externalConfigurationPb; } @@ -654,6 +790,31 @@ static ExternalTableDefinition fromPb(Table tablePb) { if (tablePb.getMaxStaleness() != null) { builder.setMaxStaleness(tablePb.getMaxStaleness()); } + if (externalDataConfiguration.getTimeZone() != null) { + builder.setTimeZone(externalDataConfiguration.getTimeZone()); + } + if (externalDataConfiguration.getDateFormat() != null) { + builder.setDateFormat(externalDataConfiguration.getDateFormat()); + } + if (externalDataConfiguration.getDatetimeFormat() != null) { + builder.setDatetimeFormat(externalDataConfiguration.getDatetimeFormat()); + } + if (externalDataConfiguration.getTimeFormat() != null) { + builder.setTimeFormat(externalDataConfiguration.getTimeFormat()); + } + if (externalDataConfiguration.getTimestampFormat() != null) { + builder.setTimestampFormat(externalDataConfiguration.getTimestampFormat()); + } + if (externalDataConfiguration.getCsvOptions() != null) { + if (externalDataConfiguration.getCsvOptions().getSourceColumnMatch() != null) { + builder.setSourceColumnMatch( + SourceColumnMatch.valueOf( + externalDataConfiguration.getCsvOptions().getSourceColumnMatch())); + } + if (externalDataConfiguration.getCsvOptions().getNullMarkers() != null) { + builder.setNullMarkers(externalDataConfiguration.getCsvOptions().getNullMarkers()); + } + } } return builder.build(); } @@ -724,6 +885,31 @@ static ExternalTableDefinition fromExternalDataConfiguration( if (externalDataConfiguration.getMetadataCacheMode() != null) { builder.setMetadataCacheMode(externalDataConfiguration.getMetadataCacheMode()); } + if (externalDataConfiguration.getTimeZone() != null) { + builder.setTimeZone(externalDataConfiguration.getTimeZone()); + } + if (externalDataConfiguration.getDateFormat() != null) { + builder.setDateFormat(externalDataConfiguration.getDateFormat()); + } + if (externalDataConfiguration.getDatetimeFormat() != null) { + builder.setDatetimeFormat(externalDataConfiguration.getDatetimeFormat()); + } + if (externalDataConfiguration.getTimeFormat() != null) { + builder.setTimeFormat(externalDataConfiguration.getTimeFormat()); + } + if (externalDataConfiguration.getTimestampFormat() != null) { + builder.setTimestampFormat(externalDataConfiguration.getTimeFormat()); + } + if (externalDataConfiguration.getCsvOptions() != null) { + if (externalDataConfiguration.getCsvOptions().getSourceColumnMatch() != null) { + builder.setSourceColumnMatch( + SourceColumnMatch.valueOf( + externalDataConfiguration.getCsvOptions().getSourceColumnMatch())); + } + if (externalDataConfiguration.getCsvOptions().getNullMarkers() != null) { + builder.setNullMarkers(externalDataConfiguration.getCsvOptions().getNullMarkers()); + } + } return builder.build(); } diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java index 5d1755459..0d1eb7245 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java @@ -18,7 +18,10 @@ import static com.google.common.base.Preconditions.checkNotNull; +import com.google.api.core.ApiFunction; import com.google.api.services.bigquery.model.JobConfigurationLoad; +import com.google.cloud.StringEnumType; +import com.google.cloud.StringEnumValue; import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; @@ -63,6 +66,55 @@ public final class LoadJobConfiguration extends JobConfiguration implements Load private final List connectionProperties; private final Boolean createSession; private final String reservation; + private final String timeZone; + private final String dateFormat; + private final String datetimeFormat; + private final String timeFormat; + private final String timestampFormat; + private final SourceColumnMatch sourceColumnMatch; + private final List nullMarkers; + + public static final class SourceColumnMatch extends StringEnumValue { + private static final long serialVersionUID = 818920627219751207L; + private static final ApiFunction CONSTRUCTOR = + new ApiFunction() { + @Override + public SourceColumnMatch apply(String constant) { + return new SourceColumnMatch(constant); + } + }; + + private static final StringEnumType type = + new StringEnumType(SourceColumnMatch.class, CONSTRUCTOR); + + public static final SourceColumnMatch SOURCE_COLUMN_MATCH_UNSPECIFIED = + type.createAndRegister("SOURCE_COLUMN_MATCH_UNSPECIFIED"); + public static final SourceColumnMatch POSITION = type.createAndRegister("POSITION"); + + public static final SourceColumnMatch NAME = type.createAndRegister("NAME"); + + private SourceColumnMatch(String constant) { + super(constant); + } + + /** + * Get the SourceColumnMatch for the given String constant, and throw an exception if the + * constant is not recognized. + */ + public static SourceColumnMatch valueOfStrict(String constant) { + return type.valueOfStrict(constant); + } + + /** Get the SourceColumnMatch for the given String constant, and allow unrecognized values. */ + public static SourceColumnMatch valueOf(String constant) { + return type.valueOf(constant); + } + + /** Return the known values for SourceColumnMatch. */ + public static SourceColumnMatch[] values() { + return type.values(); + } + } public static final class Builder extends JobConfiguration.Builder implements LoadConfiguration.Builder { @@ -95,6 +147,13 @@ public static final class Builder extends JobConfiguration.Builder connectionProperties; private Boolean createSession; private String reservation; + private String timeZone; + private String dateFormat; + private String datetimeFormat; + private String timeFormat; + private String timestampFormat; + private SourceColumnMatch sourceColumnMatch; + private List nullMarkers; private Builder() { super(Type.LOAD); @@ -129,6 +188,13 @@ private Builder(LoadJobConfiguration loadConfiguration) { this.connectionProperties = loadConfiguration.connectionProperties; this.createSession = loadConfiguration.createSession; this.reservation = loadConfiguration.reservation; + this.timeZone = loadConfiguration.timeZone; + this.dateFormat = loadConfiguration.dateFormat; + this.datetimeFormat = loadConfiguration.datetimeFormat; + this.timeFormat = loadConfiguration.timeFormat; + this.timestampFormat = loadConfiguration.timestampFormat; + this.sourceColumnMatch = loadConfiguration.sourceColumnMatch; + this.nullMarkers = loadConfiguration.nullMarkers; } private Builder(com.google.api.services.bigquery.model.JobConfiguration configurationPb) { @@ -238,6 +304,28 @@ private Builder(com.google.api.services.bigquery.model.JobConfiguration configur if (configurationPb.getReservation() != null) { this.reservation = configurationPb.getReservation(); } + if (loadConfigurationPb.getTimeZone() != null) { + this.timeZone = loadConfigurationPb.getTimeZone(); + } + if (loadConfigurationPb.getDateFormat() != null) { + this.dateFormat = loadConfigurationPb.getDateFormat(); + } + if (loadConfigurationPb.getDatetimeFormat() != null) { + this.datetimeFormat = loadConfigurationPb.getDatetimeFormat(); + } + if (loadConfigurationPb.getTimeFormat() != null) { + this.timeFormat = loadConfigurationPb.getTimeFormat(); + } + if (loadConfigurationPb.getTimestampFormat() != null) { + this.timestampFormat = loadConfigurationPb.getTimestampFormat(); + } + if (loadConfigurationPb.getSourceColumnMatch() != null) { + this.sourceColumnMatch = + SourceColumnMatch.valueOf(loadConfigurationPb.getSourceColumnMatch()); + } + if (loadConfigurationPb.getNullMarkers() != null) { + this.nullMarkers = loadConfigurationPb.getNullMarkers(); + } } @Override @@ -449,6 +537,62 @@ public Builder setReservation(String reservation) { return this; } + /** + * [Experimental] Default time zone that will apply when parsing timestamp values that have no + * specific time zone. + */ + public Builder setTimeZone(String timeZone) { + this.timeZone = timeZone; + return this; + } + + /** Date format used for parsing DATE values. */ + public Builder setDateFormat(String dateFormat) { + this.dateFormat = dateFormat; + return this; + } + + /** Date format used for parsing DATETIME values. */ + public Builder setDatetimeFormat(String datetimeFormat) { + this.datetimeFormat = datetimeFormat; + return this; + } + + /** Date format used for parsing TIME values. */ + public Builder setTimeFormat(String timeFormat) { + this.timeFormat = timeFormat; + return this; + } + + /** Date format used for parsing TIMESTAMP values. */ + public Builder setTimestampFormat(String timestampFormat) { + this.timestampFormat = timestampFormat; + return this; + } + + /** + * Controls the strategy used to match loaded columns to the schema. If not set, a sensible + * default is chosen based on how the schema is provided. If autodetect is used, then columns + * are matched by name. Otherwise, columns are matched by position. This is done to keep the + * behavior backward-compatible. + */ + public Builder setSourceColumnMatch(SourceColumnMatch sourceColumnMatch) { + this.sourceColumnMatch = sourceColumnMatch; + return this; + } + + /** + * A list of strings represented as SQL NULL value in a CSV file. null_marker and null_markers + * can't be set at the same time. If null_marker is set, null_markers has to be not set. If + * null_markers is set, null_marker has to be not set. If both null_marker and null_markers are + * set at the same time, a user error would be thrown. Any strings listed in null_markers, + * including empty string would be interpreted as SQL NULL. This applies to all column types. + */ + public Builder setNullMarkers(List nullMarkers) { + this.nullMarkers = nullMarkers; + return this; + } + @Override public LoadJobConfiguration build() { return new LoadJobConfiguration(this); @@ -483,6 +627,13 @@ private LoadJobConfiguration(Builder builder) { this.connectionProperties = builder.connectionProperties; this.createSession = builder.createSession; this.reservation = builder.reservation; + this.timeZone = builder.timeZone; + this.dateFormat = builder.dateFormat; + this.datetimeFormat = builder.datetimeFormat; + this.timeFormat = builder.timeFormat; + this.timestampFormat = builder.timestampFormat; + this.sourceColumnMatch = builder.sourceColumnMatch; + this.nullMarkers = builder.nullMarkers; } @Override @@ -634,6 +785,44 @@ public String getReservation() { return reservation; } + /** + * Returns the time zone used when parsing timestamp values that don't have specific time zone + * information. + */ + public String getTimeZone() { + return timeZone; + } + + /** Returns the format used to parse DATE values. */ + public String getDateFormat() { + return dateFormat; + } + + /** Returns the format used to parse DATETIME values. */ + public String getDatetimeFormat() { + return datetimeFormat; + } + + /** Returns the format used to parse TIME values. */ + public String getTimeFormat() { + return timeFormat; + } + + /** Returns the format used to parse TIMESTAMP values. */ + public String getTimestampFormat() { + return timestampFormat; + } + + /** Returns the strategy used to match loaded columns to the schema, either POSITION or NAME. */ + public SourceColumnMatch getSourceColumnMatch() { + return sourceColumnMatch; + } + + /** Returns a list of strings represented as SQL NULL value in a CSV file. */ + public List getNullMarkers() { + return nullMarkers; + } + @Override public Builder toBuilder() { return new Builder(this); @@ -667,7 +856,14 @@ ToStringHelper toStringHelper() { .add("referenceFileSchemaUri", referenceFileSchemaUri) .add("connectionProperties", connectionProperties) .add("createSession", createSession) - .add("reservation", reservation); + .add("reservation", reservation) + .add("timeZone", timeZone) + .add("dateFormat", dateFormat) + .add("datetimeFormat", datetimeFormat) + .add("timeFormat", timeFormat) + .add("timestampFormat", timestampFormat) + .add("sourceColumnMatch", sourceColumnMatch) + .add("nullMarkers", nullMarkers); } @Override @@ -789,6 +985,27 @@ com.google.api.services.bigquery.model.JobConfiguration toPb() { if (reservation != null) { jobConfiguration.setReservation(reservation); } + if (timeZone != null) { + loadConfigurationPb.setTimeZone(timeZone); + } + if (dateFormat != null) { + loadConfigurationPb.setDateFormat(dateFormat); + } + if (datetimeFormat != null) { + loadConfigurationPb.setDatetimeFormat(datetimeFormat); + } + if (timeFormat != null) { + loadConfigurationPb.setTimeFormat(timeFormat); + } + if (timestampFormat != null) { + loadConfigurationPb.setTimestampFormat(timestampFormat); + } + if (sourceColumnMatch != null) { + loadConfigurationPb.setSourceColumnMatch(sourceColumnMatch.toString()); + } + if (nullMarkers != null) { + loadConfigurationPb.setNullMarkers(nullMarkers); + } jobConfiguration.setLoad(loadConfigurationPb); return jobConfiguration; diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ExternalTableDefinitionTest.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ExternalTableDefinitionTest.java index 93a4425df..cb7578c75 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ExternalTableDefinitionTest.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ExternalTableDefinitionTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import com.google.cloud.bigquery.ExternalTableDefinition.SourceColumnMatch; import com.google.common.collect.ImmutableList; import java.util.List; import org.junit.Test; @@ -61,6 +62,13 @@ public class ExternalTableDefinitionTest { private static final String OBJECT_METADATA = "SIMPLE"; private static final String METADATA_CACHE_MODE = "AUTOMATIC"; private static final String MAX_STALENESS = "INTERVAL 15 MINUTE"; + private static final String TIME_ZONE = "America/Los_Angeles"; + private static final String DATE_FORMAT = "YYYY-MM-DD"; + private static final String DATETIME_FORMAT = "YYYY-MM-DD HH:MI:SS"; + private static final String TIME_FORMAT = "HH:MI:SS"; + private static final String TIMESTAMP_FORMAT = "YYYY-MM-DD HH:MI:SS"; + private static final SourceColumnMatch SOURCE_COLUMN_MATCH = SourceColumnMatch.POSITION; + private static final List NULL_MARKERS = ImmutableList.of("SQL NULL", "TEST_MARKER"); private static final ExternalTableDefinition EXTERNAL_TABLE_DEFINITION = ExternalTableDefinition.newBuilder(SOURCE_URIS, TABLE_SCHEMA, CSV_OPTIONS) .setFileSetSpecType("FILE_SET_SPEC_TYPE_FILE_SYSTEM_MATCH") @@ -74,6 +82,13 @@ public class ExternalTableDefinitionTest { .setObjectMetadata(OBJECT_METADATA) .setMetadataCacheMode(METADATA_CACHE_MODE) .setMaxStaleness(MAX_STALENESS) + .setTimeZone(TIME_ZONE) + .setDateFormat(DATE_FORMAT) + .setDatetimeFormat(DATETIME_FORMAT) + .setTimeFormat(TIME_FORMAT) + .setTimestampFormat(TIMESTAMP_FORMAT) + .setSourceColumnMatch(SOURCE_COLUMN_MATCH) + .setNullMarkers(NULL_MARKERS) .build(); private static final ExternalTableDefinition EXTERNAL_TABLE_DEFINITION_AVRO = @@ -131,6 +146,13 @@ public void testBuilder() { assertEquals(DECIMAL_TARGET_TYPES, EXTERNAL_TABLE_DEFINITION.getDecimalTargetTypes()); assertEquals(AUTODETECT, EXTERNAL_TABLE_DEFINITION.getAutodetect()); assertEquals(HIVE_PARTITIONING_OPTIONS, EXTERNAL_TABLE_DEFINITION.getHivePartitioningOptions()); + assertEquals(TIME_ZONE, EXTERNAL_TABLE_DEFINITION.getTimeZone()); + assertEquals(DATE_FORMAT, EXTERNAL_TABLE_DEFINITION.getDateFormat()); + assertEquals(DATETIME_FORMAT, EXTERNAL_TABLE_DEFINITION.getDatetimeFormat()); + assertEquals(TIME_FORMAT, EXTERNAL_TABLE_DEFINITION.getTimeFormat()); + assertEquals(TIMESTAMP_FORMAT, EXTERNAL_TABLE_DEFINITION.getTimestampFormat()); + assertEquals(SOURCE_COLUMN_MATCH, EXTERNAL_TABLE_DEFINITION.getSourceColumnMatch()); + assertEquals(NULL_MARKERS, EXTERNAL_TABLE_DEFINITION.getNullMarkers()); assertNotEquals(EXTERNAL_TABLE_DEFINITION, TableDefinition.Type.EXTERNAL); } @@ -174,5 +196,12 @@ private void compareExternalTableDefinition( assertEquals(expected.getObjectMetadata(), value.getObjectMetadata()); assertEquals(expected.getMetadataCacheMode(), value.getMetadataCacheMode()); assertEquals(expected.getMaxStaleness(), value.getMaxStaleness()); + assertEquals(expected.getTimeZone(), value.getTimeZone()); + assertEquals(expected.getDateFormat(), value.getDateFormat()); + assertEquals(expected.getDatetimeFormat(), value.getDatetimeFormat()); + assertEquals(expected.getTimeFormat(), value.getTimeFormat()); + assertEquals(expected.getTimestampFormat(), value.getTimestampFormat()); + assertEquals(expected.getSourceColumnMatch(), value.getSourceColumnMatch()); + assertEquals(expected.getNullMarkers(), value.getNullMarkers()); } } diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/LoadJobConfigurationTest.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/LoadJobConfigurationTest.java index 6d181a328..b1a2f1af8 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/LoadJobConfigurationTest.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/LoadJobConfigurationTest.java @@ -21,6 +21,7 @@ import com.google.cloud.bigquery.JobInfo.CreateDisposition; import com.google.cloud.bigquery.JobInfo.SchemaUpdateOption; import com.google.cloud.bigquery.JobInfo.WriteDisposition; +import com.google.cloud.bigquery.LoadJobConfiguration.SourceColumnMatch; import com.google.cloud.bigquery.TimePartitioning.Type; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -77,6 +78,13 @@ public class LoadJobConfigurationTest { private static final String KEY = "session_id"; private static final String VALUE = "session_id_1234567890"; + private static final String TIME_ZONE = "America/Los_Angeles"; + private static final String DATE_FORMAT = "YYYY-MM-DD"; + private static final String DATETIME_FORMAT = "YYYY-MM-DD HH:MI:SS"; + private static final String TIME_FORMAT = "HH:MI:SS"; + private static final String TIMESTAMP_FORMAT = "YYYY-MM-DD HH:MI:SS"; + private static final SourceColumnMatch SOURCE_COLUMN_MATCH = SourceColumnMatch.POSITION; + private static final List NULL_MARKERS = ImmutableList.of("SQL NULL", "TEST MARKER"); private static final ConnectionProperty CONNECTION_PROPERTY = ConnectionProperty.newBuilder().setKey(KEY).setValue(VALUE).build(); private static final List CONNECTION_PROPERTIES = @@ -110,6 +118,13 @@ public class LoadJobConfigurationTest { .setConnectionProperties(CONNECTION_PROPERTIES) .setCreateSession(CREATE_SESSION) .setReservation(RESERVATION) + .setTimeZone(TIME_ZONE) + .setDateFormat(DATE_FORMAT) + .setDatetimeFormat(DATETIME_FORMAT) + .setTimeFormat(TIME_FORMAT) + .setTimestampFormat(TIMESTAMP_FORMAT) + .setSourceColumnMatch(SOURCE_COLUMN_MATCH) + .setNullMarkers(NULL_MARKERS) .build(); private static final DatastoreBackupOptions BACKUP_OPTIONS = @@ -271,5 +286,12 @@ private void compareLoadJobConfiguration( assertEquals(expected.getConnectionProperties(), value.getConnectionProperties()); assertEquals(expected.getCreateSession(), value.getCreateSession()); assertEquals(expected.getReservation(), value.getReservation()); + assertEquals(expected.getTimeZone(), value.getTimeZone()); + assertEquals(expected.getDateFormat(), value.getDateFormat()); + assertEquals(expected.getDatetimeFormat(), value.getDatetimeFormat()); + assertEquals(expected.getTimeFormat(), value.getTimeFormat()); + assertEquals(expected.getTimestampFormat(), value.getTimestampFormat()); + assertEquals(expected.getSourceColumnMatch(), value.getSourceColumnMatch()); + assertEquals(expected.getNullMarkers(), value.getNullMarkers()); } } From 8aabfa76ac8d55a6a3d49b76ac85abd011411fc6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 2 Jul 2025 15:54:42 +0200 Subject: [PATCH 10/16] chore(deps): update dependency com.google.cloud:libraries-bom to v26.63.0 (#3874) --- samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 8b1e77bd3..62c7f22ec 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -47,7 +47,7 @@ com.google.cloud libraries-bom - 26.62.0 + 26.63.0 pom import From d2918da844cd20ca1602c6fcf9fa1df685f261fc Mon Sep 17 00:00:00 2001 From: Phong Chuong <147636638+PhongChuong@users.noreply.github.com> Date: Fri, 4 Jul 2025 13:16:25 -0400 Subject: [PATCH 11/16] docs: update maven format command (#3877) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0599033d7..5456fad05 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,7 +88,7 @@ Code in this repo is formatted with [google-java-format](https://github.com/google/google-java-format). To run formatting on your project, you can run: ``` -mvn com.coveo:fmt-maven-plugin:format +mvn com.spotify.fmt:fmt-maven-plugin:format ``` [1]: https://cloud.google.com/docs/authentication/getting-started#creating_a_service_account From 0e971b8ace013caa31b8a02a21038e94bebae2a5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 9 Jul 2025 16:57:01 +0200 Subject: [PATCH 12/16] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.50.1 (#3878) --- .github/workflows/unmanaged_dependency_check.yaml | 2 +- .kokoro/continuous/graalvm-native-a.cfg | 2 +- .kokoro/continuous/graalvm-native-b.cfg | 2 +- .kokoro/continuous/graalvm-native-c.cfg | 2 +- .kokoro/presubmit/graalvm-native-a.cfg | 2 +- .kokoro/presubmit/graalvm-native-b.cfg | 2 +- .kokoro/presubmit/graalvm-native-c.cfg | 2 +- google-cloud-bigquery-bom/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/unmanaged_dependency_check.yaml b/.github/workflows/unmanaged_dependency_check.yaml index 63543a40f..1795d3b24 100644 --- a/.github/workflows/unmanaged_dependency_check.yaml +++ b/.github/workflows/unmanaged_dependency_check.yaml @@ -17,7 +17,7 @@ jobs: # repository .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.1 with: # java-bigquery does not produce a BOM. Fortunately the root pom.xml # defines google-cloud-bigquery in dependencyManagement section. So diff --git a/.kokoro/continuous/graalvm-native-a.cfg b/.kokoro/continuous/graalvm-native-a.cfg index dfa34060b..13d12ce34 100644 --- a/.kokoro/continuous/graalvm-native-a.cfg +++ b/.kokoro/continuous/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.1" } env_vars: { diff --git a/.kokoro/continuous/graalvm-native-b.cfg b/.kokoro/continuous/graalvm-native-b.cfg index 37dda4ab5..4696d04ef 100644 --- a/.kokoro/continuous/graalvm-native-b.cfg +++ b/.kokoro/continuous/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.1" } env_vars: { diff --git a/.kokoro/continuous/graalvm-native-c.cfg b/.kokoro/continuous/graalvm-native-c.cfg index a8ab97784..26d39a747 100644 --- a/.kokoro/continuous/graalvm-native-c.cfg +++ b/.kokoro/continuous/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.1" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-a.cfg b/.kokoro/presubmit/graalvm-native-a.cfg index dfa34060b..13d12ce34 100644 --- a/.kokoro/presubmit/graalvm-native-a.cfg +++ b/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.1" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-b.cfg b/.kokoro/presubmit/graalvm-native-b.cfg index 37dda4ab5..4696d04ef 100644 --- a/.kokoro/presubmit/graalvm-native-b.cfg +++ b/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.1" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-c.cfg b/.kokoro/presubmit/graalvm-native-c.cfg index a8ab97784..26d39a747 100644 --- a/.kokoro/presubmit/graalvm-native-c.cfg +++ b/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.1" } env_vars: { diff --git a/google-cloud-bigquery-bom/pom.xml b/google-cloud-bigquery-bom/pom.xml index 1194e1b0e..8af53ddad 100644 --- a/google-cloud-bigquery-bom/pom.xml +++ b/google-cloud-bigquery-bom/pom.xml @@ -8,7 +8,7 @@ com.google.cloud sdk-platform-java-config - 3.50.0 + 3.50.1 diff --git a/pom.xml b/pom.xml index 433cb320c..5c10cf019 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.50.0 + 3.50.1 From 5cfdf855fa0cf206660fd89743cbaabf3afa75a3 Mon Sep 17 00:00:00 2001 From: Phong Chuong <147636638+PhongChuong@users.noreply.github.com> Date: Wed, 9 Jul 2025 21:01:49 -0400 Subject: [PATCH 13/16] fix: load jobs preserve ascii control characters configuration (#3876) * fix: load jobs preserve ascii control characters configuration * fix lint * fix NPE * fix NPE --- .../cloud/bigquery/LoadJobConfiguration.java | 6 ++++ .../bigquery/LoadJobConfigurationTest.java | 1 + .../cloud/bigquery/it/ITBigQueryTest.java | 29 +++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java index 0d1eb7245..381942cd0 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/LoadJobConfiguration.java @@ -219,6 +219,7 @@ private Builder(com.google.api.services.bigquery.model.JobConfiguration configur this.nullMarker = loadConfigurationPb.getNullMarker(); } if (loadConfigurationPb.getAllowJaggedRows() != null + || loadConfigurationPb.getPreserveAsciiControlCharacters() != null || loadConfigurationPb.getAllowQuotedNewlines() != null || loadConfigurationPb.getEncoding() != null || loadConfigurationPb.getFieldDelimiter() != null @@ -229,6 +230,10 @@ private Builder(com.google.api.services.bigquery.model.JobConfiguration configur .setEncoding(loadConfigurationPb.getEncoding()) .setFieldDelimiter(loadConfigurationPb.getFieldDelimiter()) .setQuote(loadConfigurationPb.getQuote()); + if (loadConfigurationPb.getPreserveAsciiControlCharacters() != null) { + builder.setPreserveAsciiControlCharacters( + loadConfigurationPb.getPreserveAsciiControlCharacters()); + } if (loadConfigurationPb.getAllowJaggedRows() != null) { builder.setAllowJaggedRows(loadConfigurationPb.getAllowJaggedRows()); } @@ -907,6 +912,7 @@ com.google.api.services.bigquery.model.JobConfiguration toPb() { .setAllowJaggedRows(csvOptions.allowJaggedRows()) .setAllowQuotedNewlines(csvOptions.allowQuotedNewLines()) .setEncoding(csvOptions.getEncoding()) + .setPreserveAsciiControlCharacters(csvOptions.getPreserveAsciiControlCharacters()) .setQuote(csvOptions.getQuote()); if (csvOptions.getSkipLeadingRows() != null) { // todo(mziccard) remove checked cast or comment when #1044 is closed diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/LoadJobConfigurationTest.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/LoadJobConfigurationTest.java index b1a2f1af8..d987eb28e 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/LoadJobConfigurationTest.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/LoadJobConfigurationTest.java @@ -38,6 +38,7 @@ public class LoadJobConfigurationTest { .setAllowJaggedRows(true) .setAllowQuotedNewLines(false) .setEncoding(StandardCharsets.UTF_8) + .setPreserveAsciiControlCharacters(true) .build(); private static final TableId TABLE_ID = TableId.of("dataset", "table"); private static final CreateDisposition CREATE_DISPOSITION = CreateDisposition.CREATE_IF_NEEDED; diff --git a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java index f188e7946..c9f6296cc 100644 --- a/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java +++ b/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java @@ -613,6 +613,7 @@ public class ITBigQueryTest { private static final String LOAD_FILE_LARGE = "load_large.csv"; private static final String LOAD_FILE_FLEXIBLE_COLUMN_NAME = "load_flexible_column_name.csv"; + private static final String LOAD_FILE_NULL = "load_null.csv"; private static final String JSON_LOAD_FILE = "load.json"; private static final String JSON_LOAD_FILE_BQ_RESULTSET = "load_bq_resultset.json"; private static final String JSON_LOAD_FILE_SIMPLE = "load_simple.json"; @@ -628,6 +629,7 @@ public class ITBigQueryTest { private static final TableId TABLE_ID_FASTQUERY_BQ_RESULTSET = TableId.of(DATASET, "fastquery_testing_bq_resultset"); private static final String CSV_CONTENT = "StringValue1\nStringValue2\n"; + private static final String CSV_CONTENT_NULL = "String\0Value1\n"; private static final String CSV_CONTENT_FLEXIBLE_COLUMN = "name,&ersand\nrow_name,1"; private static final String JSON_CONTENT = @@ -1080,6 +1082,9 @@ public static void beforeClass() throws InterruptedException, IOException { storage.create( BlobInfo.newBuilder(BUCKET, LOAD_FILE).setContentType("text/plain").build(), CSV_CONTENT.getBytes(StandardCharsets.UTF_8)); + storage.create( + BlobInfo.newBuilder(BUCKET, LOAD_FILE_NULL).setContentType("text/plain").build(), + CSV_CONTENT_NULL.getBytes(StandardCharsets.UTF_8)); storage.create( BlobInfo.newBuilder(BUCKET, LOAD_FILE_FLEXIBLE_COLUMN_NAME) .setContentType("text/plain") @@ -6600,9 +6605,9 @@ public void testLocation() throws Exception { } @Test - public void testPreserveAsciiControlCharacters() + public void testWriteChannelPreserveAsciiControlCharacters() throws InterruptedException, IOException, TimeoutException { - String destinationTableName = "test_preserve_ascii_control_characters"; + String destinationTableName = "test_write_channel_preserve_ascii_control_characters"; TableId tableId = TableId.of(DATASET, destinationTableName); WriteChannelConfiguration configuration = WriteChannelConfiguration.newBuilder(tableId) @@ -6625,6 +6630,26 @@ public void testPreserveAsciiControlCharacters() assertTrue(bigquery.delete(tableId)); } + @Test + public void testLoadJobPreserveAsciiControlCharacters() throws InterruptedException { + String destinationTableName = "test_load_job_preserve_ascii_control_characters"; + TableId destinationTable = TableId.of(DATASET, destinationTableName); + + try { + LoadJobConfiguration configuration = + LoadJobConfiguration.newBuilder(destinationTable, "gs://" + BUCKET + "/" + LOAD_FILE_NULL) + .setFormatOptions( + CsvOptions.newBuilder().setPreserveAsciiControlCharacters(true).build()) + .setSchema(SIMPLE_SCHEMA) + .build(); + Job remoteLoadJob = bigquery.create(JobInfo.of(configuration)); + remoteLoadJob = remoteLoadJob.waitFor(); + assertNull(remoteLoadJob.getStatus().getError()); + } finally { + assertTrue(bigquery.delete(destinationTable)); + } + } + @Test public void testReferenceFileSchemaUriForAvro() { try { From c47a062136fea4de91190cafb1f11bac6abbbe3a Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Thu, 10 Jul 2025 11:38:38 -0700 Subject: [PATCH 14/16] feat: next release from main branch is 2.53.0 (#3879) --- .github/release-please.yml | 4 ++++ .github/sync-repo-settings.yaml | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/.github/release-please.yml b/.github/release-please.yml index 48231f76e..d722d35a2 100644 --- a/.github/release-please.yml +++ b/.github/release-please.yml @@ -31,6 +31,10 @@ branches: handleGHRelease: true releaseType: java-backport branch: 2.48.x + - bumpMinorPreMajor: true + handleGHRelease: true + releaseType: java-backport + branch: 2.52.x bumpMinorPreMajor: true handleGHRelease: true releaseType: java-yoshi diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index c3a3263dd..26f85cb16 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -132,6 +132,21 @@ branchProtectionRules: - cla/google - javadoc - unmanaged_dependency_check + - pattern: 2.52.x + isAdminEnforced: true + requiredApprovingReviewCount: 1 + requiresCodeOwnerReviews: true + requiresStrictStatusChecks: false + requiredStatusCheckContexts: + - dependencies (17) + - lint + - clirr + - units (8) + - units (11) + - 'Kokoro - Test: Integration' + - cla/google + - javadoc + - unmanaged_dependency_check permissionRules: - team: api-bigquery permission: admin From 3a17ec2c7e0e2f2c0960d07a92bc09cac9dc8ab7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 14 Jul 2025 17:03:06 +0200 Subject: [PATCH 15/16] chore(deps): update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.16.0 (#3884) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5c10cf019..d44a03bef 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-bigquerystorage-bom - 3.15.3 + 3.16.0 pom import From ed331354e225d9340c6101b9e783a1b79eae2875 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 14 Jul 2025 12:59:52 -0400 Subject: [PATCH 16/16] chore(main): release 2.53.0 (#3866) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ benchmark/pom.xml | 2 +- google-cloud-bigquery-bom/pom.xml | 4 ++-- google-cloud-bigquery/pom.xml | 4 ++-- pom.xml | 4 ++-- samples/snapshot/pom.xml | 2 +- versions.txt | 2 +- 7 files changed, 35 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71577758b..9336a4195 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [2.53.0](https://github.com/googleapis/java-bigquery/compare/v2.52.0...v2.53.0) (2025-07-14) + + +### Features + +* **bigquery:** Add OpenTelemetry support to BQ rpcs ([#3860](https://github.com/googleapis/java-bigquery/issues/3860)) ([e2d23c1](https://github.com/googleapis/java-bigquery/commit/e2d23c1b15f2c48a4113f82b920f5c29c4b5dfea)) +* **bigquery:** Add support for custom timezones and timestamps ([#3859](https://github.com/googleapis/java-bigquery/issues/3859)) ([e5467c9](https://github.com/googleapis/java-bigquery/commit/e5467c917c63ac066edcbcd902cc2093a39971a3)) +* Next release from main branch is 2.53.0 ([#3879](https://github.com/googleapis/java-bigquery/issues/3879)) ([c47a062](https://github.com/googleapis/java-bigquery/commit/c47a062136fea4de91190cafb1f11bac6abbbe3a)) + + +### Bug Fixes + +* Load jobs preserve ascii control characters configuration ([#3876](https://github.com/googleapis/java-bigquery/issues/3876)) ([5cfdf85](https://github.com/googleapis/java-bigquery/commit/5cfdf855fa0cf206660fd89743cbaabf3afa75a3)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-bigqueryconnection-v1 to v2.69.0 ([#3870](https://github.com/googleapis/java-bigquery/issues/3870)) ([a7f1007](https://github.com/googleapis/java-bigquery/commit/a7f1007b5242da2c0adebbb309a908d7d4db5974)) +* Update dependency com.google.apis:google-api-services-bigquery to v2-rev20250615-2.0.0 ([#3872](https://github.com/googleapis/java-bigquery/issues/3872)) ([f081589](https://github.com/googleapis/java-bigquery/commit/f08158955b7fec3c2ced6332b6e4d76cc13f2e90)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.50.1 ([#3878](https://github.com/googleapis/java-bigquery/issues/3878)) ([0e971b8](https://github.com/googleapis/java-bigquery/commit/0e971b8ace013caa31b8a02a21038e94bebae2a5)) + + +### Documentation + +* Update maven format command ([#3877](https://github.com/googleapis/java-bigquery/issues/3877)) ([d2918da](https://github.com/googleapis/java-bigquery/commit/d2918da844cd20ca1602c6fcf9fa1df685f261fc)) + ## [2.52.0](https://github.com/googleapis/java-bigquery/compare/v2.51.0...v2.52.0) (2025-06-25) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 8fcf7ca00..8674b7102 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -6,7 +6,7 @@ google-cloud-bigquery-parent com.google.cloud - 2.52.1-SNAPSHOT + 2.53.0 diff --git a/google-cloud-bigquery-bom/pom.xml b/google-cloud-bigquery-bom/pom.xml index 8af53ddad..bc3a9e0c3 100644 --- a/google-cloud-bigquery-bom/pom.xml +++ b/google-cloud-bigquery-bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-bigquery-bom - 2.52.1-SNAPSHOT + 2.53.0 pom com.google.cloud @@ -54,7 +54,7 @@ com.google.cloud google-cloud-bigquery - 2.52.1-SNAPSHOT + 2.53.0 diff --git a/google-cloud-bigquery/pom.xml b/google-cloud-bigquery/pom.xml index 6c7e1aed1..ad20f607e 100644 --- a/google-cloud-bigquery/pom.xml +++ b/google-cloud-bigquery/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-bigquery - 2.52.1-SNAPSHOT + 2.53.0 jar BigQuery https://github.com/googleapis/java-bigquery @@ -11,7 +11,7 @@ com.google.cloud google-cloud-bigquery-parent - 2.52.1-SNAPSHOT + 2.53.0 google-cloud-bigquery diff --git a/pom.xml b/pom.xml index d44a03bef..4bc7652ba 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-bigquery-parent pom - 2.52.1-SNAPSHOT + 2.53.0 BigQuery Parent https://github.com/googleapis/java-bigquery @@ -93,7 +93,7 @@ com.google.cloud google-cloud-bigquery - 2.52.1-SNAPSHOT + 2.53.0 diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index d9d52314b..7e1bfd314 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -44,7 +44,7 @@ com.google.cloud google-cloud-bigquery - 2.52.1-SNAPSHOT + 2.53.0 diff --git a/versions.txt b/versions.txt index 5e931b82a..5245c445b 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-bigquery:2.52.0:2.52.1-SNAPSHOT \ No newline at end of file +google-cloud-bigquery:2.53.0:2.53.0 \ No newline at end of file