Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,20 @@ If you are using Maven without the BOM, add this to your dependencies:
If you are using Gradle 5.x or later, add this to your dependencies:

```Groovy
implementation platform('com.google.cloud:libraries-bom:26.18.0')
implementation platform('com.google.cloud:libraries-bom:26.19.0')

implementation 'com.google.cloud:google-cloud-bigquery'
```
If you are using Gradle without BOM, add this to your dependencies:

```Groovy
implementation 'com.google.cloud:google-cloud-bigquery:2.30.0'
implementation 'com.google.cloud:google-cloud-bigquery:2.30.1'
```

If you are using SBT, add this to your dependencies:

```Scala
libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "2.30.0"
libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "2.30.1"
```
<!-- {x-version-update-end} -->

Expand Down Expand Up @@ -351,7 +351,7 @@ Java is a registered trademark of Oracle and/or its affiliates.
[kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-bigquery/java11.html
[stability-image]: https://img.shields.io/badge/stability-stable-green
[maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-bigquery.svg
[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-bigquery/2.30.0
[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-bigquery/2.30.1
[authentication]: https://github.com/googleapis/google-cloud-java#authentication
[auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes
[predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.threeten.bp.Instant;
import org.threeten.bp.temporal.ChronoUnit;

final class BigQueryImpl extends BaseService<BigQueryOptions> implements BigQuery {

Expand Down Expand Up @@ -422,15 +426,38 @@ public com.google.api.services.bigquery.model.Job call() {
}

if (!idRandom) {
if (createException instanceof BigQueryException && createException.getCause() != null) {

/*GoogleJsonResponseException createExceptionCause =
(GoogleJsonResponseException) createException.getCause();*/

Pattern pattern = Pattern.compile(".*Already.*Exists:.*Job.*", Pattern.CASE_INSENSITIVE);
Comment thread
Neenu1995 marked this conversation as resolved.
Matcher matcher = pattern.matcher(createException.getCause().getMessage());

if (matcher.find()) {
// If the Job ALREADY EXISTS, retrieve it.
Job job = this.getJob(jobInfo.getJobId());

long jobCreationTime = job.getStatistics().getCreationTime();
long jobMinStaleTime = System.currentTimeMillis();
long jobMaxStaleTime =
Instant.ofEpochMilli(jobMinStaleTime).minus(1, ChronoUnit.DAYS).toEpochMilli();

// Only return the job if it has been created in the past 24 hours.
// This is assuming any job older than 24 hours is a valid duplicate JobID
// and not a false positive like b/290419183
if (jobCreationTime >= jobMaxStaleTime && jobCreationTime <= jobMinStaleTime) {
return job;
}
}
}
throw createException;
}

// If create RPC fails, it's still possible that the job has been successfully
// created,
// and get might work.
// created, and get might work.
// We can only do this if we randomly generated the ID. Otherwise we might
// mistakenly
// fetch a job created by someone else.
// mistakenly fetch a job created by someone else.
Job job;
try {
job = getJob(finalJobId[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
import com.google.cloud.bigquery.InsertAllRequest.RowToInsert;
import com.google.cloud.bigquery.InsertAllResponse;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobConfiguration;
import com.google.cloud.bigquery.JobId;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.JobStatistics;
Expand Down Expand Up @@ -6101,4 +6102,31 @@ public void testForeignKeysUpdate() {
bigquery.delete(tableIdPk2);
}
}

@Test
public void testAlreadyExistJobExceptionHandling() throws InterruptedException {
String query =
"SELECT TimestampField, StringField, BooleanField FROM "
+ DATASET
+ "."
+ TABLE_ID.getTable();
JobId jobId = JobId.newBuilder().setRandomJob().build();

JobConfiguration queryJobConfiguration = QueryJobConfiguration.newBuilder(query).build();
// Creating the job with the explicit jobID
bigquery.create(JobInfo.of(jobId, queryJobConfiguration));
// Calling the query method with the job that has already been created.
// This should throw ALREADY_EXISTS error without the exception handling added
// or if the job is older than 24 hours.
try {
bigquery.query(QueryJobConfiguration.newBuilder(query).build(), jobId);
// Test succeeds if Exception is not thrown and code flow reaches this statement.
assertTrue(true);
} catch (BigQueryException ex) {
// test fails if an exception is thrown
if (ex.getCause() != null && ex.getCause().getMessage().contains("Already Exists: Job")) {
fail("Already exists error should not be thrown");
}
}
}
}