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
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/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/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
diff --git a/benchmark/pom.xml b/benchmark/pom.xml
index bb58ca1e1..8674b7102 100644
--- a/benchmark/pom.xml
+++ b/benchmark/pom.xml
@@ -6,7 +6,7 @@
google-cloud-bigquery-parent
com.google.cloud
- 2.52.0
+ 2.53.0
diff --git a/google-cloud-bigquery-bom/pom.xml b/google-cloud-bigquery-bom/pom.xml
index 836073eb4..bc3a9e0c3 100644
--- a/google-cloud-bigquery-bom/pom.xml
+++ b/google-cloud-bigquery-bom/pom.xml
@@ -3,12 +3,12 @@
4.0.0
com.google.cloud
google-cloud-bigquery-bom
- 2.52.0
+ 2.53.0
pom
com.google.cloud
sdk-platform-java-config
- 3.50.0
+ 3.50.1
@@ -54,7 +54,7 @@
com.google.cloud
google-cloud-bigquery
- 2.52.0
+ 2.53.0
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/pom.xml b/google-cloud-bigquery/pom.xml
index 644fe0ef5..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.0
+ 2.53.0
jar
BigQuery
https://github.com/googleapis/java-bigquery
@@ -11,7 +11,7 @@
com.google.cloud
google-cloud-bigquery-parent
- 2.52.0
+ 2.53.0
google-cloud-bigquery
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..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
@@ -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) {
@@ -153,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
@@ -163,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());
}
@@ -238,6 +309,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 +542,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 +632,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 +790,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 +861,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
@@ -711,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
@@ -789,6 +991,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/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
@@ -71,7 +71,7 @@
com.google.cloud
google-cloud-bigquerystorage-bom
- 3.15.3
+ 3.16.0
pom
import
@@ -79,7 +79,7 @@
com.google.cloud
google-cloud-datacatalog-bom
- 1.72.0
+ 1.73.0
pom
import
@@ -93,7 +93,7 @@
com.google.cloud
google-cloud-bigquery
- 2.52.0
+ 2.53.0
@@ -137,19 +137,19 @@
com.google.cloud
google-cloud-storage
- 2.53.1
+ 2.53.2
test
com.google.cloud
google-cloud-bigqueryconnection
- 2.68.0
+ 2.69.0
test
com.google.api.grpc
proto-google-cloud-bigqueryconnection-v1
- 2.68.0
+ 2.69.0
test
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 4089821fe..11e13e43e 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -45,7 +45,7 @@
com.google.cloud
google-cloud-bigquery
- 2.51.0
+ 2.52.0
@@ -63,13 +63,13 @@
com.google.cloud
google-cloud-bigtable
- 2.60.0
+ 2.61.0
test
com.google.cloud
google-cloud-bigqueryconnection
- 2.68.0
+ 2.69.0
test
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 1a1655234..7e1bfd314 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.53.0
@@ -61,13 +61,13 @@
com.google.cloud
google-cloud-bigtable
- 2.60.0
+ 2.61.0
test
com.google.cloud
google-cloud-bigqueryconnection
- 2.68.0
+ 2.69.0
test
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 160e38cb0..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
@@ -79,13 +79,13 @@
com.google.cloud
google-cloud-bigtable
- 2.60.0
+ 2.61.0
test
com.google.cloud
google-cloud-bigqueryconnection
- 2.68.0
+ 2.69.0
test
diff --git a/versions.txt b/versions.txt
index 2b5922874..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.0
\ No newline at end of file
+google-cloud-bigquery:2.53.0:2.53.0
\ No newline at end of file