Skip to content

Commit d0d758a

Browse files
authored
fix: NPE for executeSelect nonFast path with empty result (#3445)
* fix: NPE for executeSelect nonFast path with empty result * remove commented out extraneous code
1 parent 3701683 commit d0d758a

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java

+10-6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import com.google.common.util.concurrent.ListeningExecutorService;
5454
import com.google.common.util.concurrent.MoreExecutors;
5555
import java.io.IOException;
56+
import java.math.BigInteger;
5657
import java.util.AbstractList;
5758
import java.util.ArrayList;
5859
import java.util.Collections;
@@ -418,12 +419,15 @@ public ListenableFuture<ExecuteSelectResponse> executeSelectAsync(
418419
@VisibleForTesting
419420
BigQueryResult getResultSet(
420421
GetQueryResultsResponse firstPage, JobId jobId, String sql, Boolean hasQueryParameters) {
421-
return getSubsequentQueryResultsWithJob(
422-
firstPage.getTotalRows().longValue(),
423-
(long) firstPage.getRows().size(),
424-
jobId,
425-
firstPage,
426-
hasQueryParameters);
422+
if (firstPage.getTotalRows().compareTo(BigInteger.ZERO) > 0) {
423+
return getSubsequentQueryResultsWithJob(
424+
firstPage.getTotalRows().longValue(),
425+
(long) firstPage.getRows().size(),
426+
jobId,
427+
firstPage,
428+
hasQueryParameters);
429+
}
430+
return new BigQueryResultImpl(Schema.fromPb(firstPage.getSchema()), 0, null, null);
427431
}
428432

429433
static class EndOfFieldValueList

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/ConnectionImplTest.java

+32-1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ public class ConnectionImplTest {
100100
.setTotalBytesProcessed(42L)
101101
.setTotalRows(BigInteger.valueOf(1L))
102102
.setSchema(FAST_QUERY_TABLESCHEMA);
103+
private static final GetQueryResultsResponse GET_QUERY_RESULTS_RESPONSE_EMPTY =
104+
new GetQueryResultsResponse()
105+
.setJobReference(QUERY_JOB.toPb())
106+
.setJobComplete(true)
107+
.setCacheHit(false)
108+
.setPageToken(PAGE_TOKEN)
109+
.setTotalBytesProcessed(0L)
110+
.setTotalRows(BigInteger.valueOf(0L))
111+
.setSchema(FAST_QUERY_TABLESCHEMA);
103112

104113
private static final GetQueryResultsResponse GET_QUERY_RESULTS_RESPONSE_NULL_SCHEMA =
105114
new GetQueryResultsResponse()
@@ -375,7 +384,6 @@ public void testLegacyQuerySinglePage() throws BigQuerySQLException {
375384
ConnectionImpl connectionSpy = Mockito.spy(connection);
376385
com.google.api.services.bigquery.model.Job jobResponseMock =
377386
new com.google.api.services.bigquery.model.Job()
378-
// .setConfiguration(QUERY_JOB.g)
379387
.setJobReference(QUERY_JOB.toPb())
380388
.setId(JOB)
381389
.setStatus(new com.google.api.services.bigquery.model.JobStatus().setState("DONE"));
@@ -401,6 +409,29 @@ public void testLegacyQuerySinglePage() throws BigQuerySQLException {
401409
.createJobForQuery(any(com.google.api.services.bigquery.model.Job.class));
402410
}
403411

412+
// calls executeSelect with a nonFast query where the query returns an empty result.
413+
@Test
414+
public void testLegacyQuerySinglePageEmptyResults() throws BigQuerySQLException {
415+
ConnectionImpl connectionSpy = Mockito.spy(connection);
416+
com.google.api.services.bigquery.model.Job jobResponseMock =
417+
new com.google.api.services.bigquery.model.Job()
418+
.setJobReference(QUERY_JOB.toPb())
419+
.setId(JOB)
420+
.setStatus(new com.google.api.services.bigquery.model.JobStatus().setState("DONE"));
421+
// emulating a legacy query
422+
doReturn(false).when(connectionSpy).isFastQuerySupported();
423+
doReturn(GET_QUERY_RESULTS_RESPONSE_EMPTY)
424+
.when(connectionSpy)
425+
.getQueryResultsFirstPage(any(JobId.class));
426+
when(bigqueryRpcMock.createJobForQuery(any(com.google.api.services.bigquery.model.Job.class)))
427+
.thenReturn(jobResponseMock); // RPC call in createQueryJob
428+
BigQueryResult res = connectionSpy.executeSelect(SQL_QUERY);
429+
assertEquals(res.getTotalRows(), 0);
430+
assertEquals(QUERY_SCHEMA, res.getSchema());
431+
verify(bigqueryRpcMock, times(1))
432+
.createJobForQuery(any(com.google.api.services.bigquery.model.Job.class));
433+
}
434+
404435
// exercises getSubsequentQueryResultsWithJob for fast running queries
405436
@Test
406437
public void testFastQueryLongRunning() throws SQLException {

0 commit comments

Comments
 (0)