Skip to content

Commit 9a0b05a

Browse files
authored
fix: NPE when reading BigQueryResultSet from empty tables (#3627)
* fix: NPE when reading BigQueryResultSet from empty tables * Add unittests
1 parent 4061922 commit 9a0b05a

File tree

4 files changed

+27
-2
lines changed

4 files changed

+27
-2
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ private class BigQueryResultSet extends AbstractJdbcResultSet {
113113
@Override
114114
/*Advances the result set to the next row, returning false if no such row exists. Potentially blocking operation*/
115115
public boolean next() throws SQLException {
116+
if (buffer == null) {
117+
return false;
118+
}
116119
if (hasReachedEnd) { // if end of stream is reached then we can simply return false
117120
return false;
118121
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ ListenableFuture<ExecuteSelectResponse> executeSelectAsync(String sql)
140140
* &#64;code
141141
* ConnectionSettings connectionSettings =
142142
* ConnectionSettings.newBuilder()
143-
* ..setUseReadAPI(true)
143+
* .setUseReadAPI(true)
144144
* .build();
145145
* Connection connection = bigquery.createConnection(connectionSettings);
146146
* String selectQuery =

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ public void testLegacyQuerySinglePage() throws BigQuerySQLException {
411411

412412
// calls executeSelect with a nonFast query where the query returns an empty result.
413413
@Test
414-
public void testLegacyQuerySinglePageEmptyResults() throws BigQuerySQLException {
414+
public void testLegacyQuerySinglePageEmptyResults() throws BigQuerySQLException, SQLException {
415415
ConnectionImpl connectionSpy = Mockito.spy(connection);
416416
com.google.api.services.bigquery.model.Job jobResponseMock =
417417
new com.google.api.services.bigquery.model.Job()
@@ -428,6 +428,10 @@ public void testLegacyQuerySinglePageEmptyResults() throws BigQuerySQLException
428428
BigQueryResult res = connectionSpy.executeSelect(SQL_QUERY);
429429
assertEquals(res.getTotalRows(), 0);
430430
assertEquals(QUERY_SCHEMA, res.getSchema());
431+
assertEquals(
432+
false,
433+
res.getResultSet()
434+
.next()); // Validates that NPE does not occur when reading from empty ResultSet.
431435
verify(bigqueryRpcMock, times(1))
432436
.createJobForQuery(any(com.google.api.services.bigquery.model.Job.class));
433437
}

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java

+18
Original file line numberDiff line numberDiff line change
@@ -3491,6 +3491,24 @@ public void testExecuteSelectDefaultConnectionSettings() throws SQLException {
34913491
assertEquals(42, bigQueryResult.getTotalRows());
34923492
}
34933493

3494+
@Test
3495+
public void testExecuteSelectReadApiEmptyResultSet() throws SQLException {
3496+
ConnectionSettings connectionSettings =
3497+
ConnectionSettings.newBuilder()
3498+
.setJobTimeoutMs(
3499+
Long.MAX_VALUE) // Force executeSelect to use ReadAPI instead of fast query.
3500+
.setUseReadAPI(true)
3501+
.setUseQueryCache(false)
3502+
.build();
3503+
Connection connection = bigquery.createConnection(connectionSettings);
3504+
String query = "SELECT TIMESTAMP '2022-01-24T23:54:25.095574Z' LIMIT 0";
3505+
BigQueryResult bigQueryResult = connection.executeSelect(query);
3506+
3507+
ResultSet rs = bigQueryResult.getResultSet();
3508+
assertThat(rs.next()).isFalse();
3509+
assertThat(bigQueryResult.getTotalRows()).isEqualTo(0);
3510+
}
3511+
34943512
@Test
34953513
public void testExecuteSelectWithCredentials() throws SQLException {
34963514
// This test validate that executeSelect uses the same credential provided by the BigQuery

0 commit comments

Comments
 (0)