googleapis / googleapis/google-cloud-java
[java-bigquery] [BigQuery] Thread will hang forever when using executeSelect if you do not iterate over the entire ResultSet
- Ngôn ngữ chính
- Java
- Star
- 2.1k
- Fork
- 1.2k
- Merge trung bình
- 1 ngày 23 giờ
- Pull request đã merge (30 ngày)
- 154
Mô tả
Testing executeSelect on Java 21 on MacOS Sonoma 14.7.6, I found a concerning issue. If your process or thread attempts to end after creating a connection and calling `executeSelect()` without iterating over the entire ResultSet until `next()` returns false, it will hang forever.
#### Steps to reproduce
1. Go through the usual steps of instantiating a BigQuery client, creating ConnectionSettings, calling `createConnection` on said client, and then call `executeSelect()` to get your BigQueryResult.
2. Either let the process end, or don't iterate over the entire ResultSet contained in the BigQueryResult. It will hang.
#### Code example
```java
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryResult;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.Connection;
import com.google.cloud.bigquery.ConnectionSettings;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BQExecuteSelectTest {
public static void main(String[] args) {
try {
if(args.length != 2)
throw new IllegalArgumentException("Usage: BQExecuteSelectTest \n - Accepts SQL on STDIN");
BigQuery bq = BigQueryOptions.newBuilder()
.setProjectId(args[0])
.setLocation(args[1]).build().getService();
ConnectionSettings settings = ConnectionSettings.newBuilder()
.setCreateSession(true)
.setMaxResultPerPage(100)
.setMaxResults(100L).build();
Connection conn = bq.createConnection(settings);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BigQueryResult res = conn.executeSelect(reader.lines().collect(Collectors.joining("\n")));
// Do nothing, or just don't finish iterating over res.getResultSet()
} catch(IllegalArgumentException e) {
System.out.println(e.getMessage());
} catch(Exception e) {
System.out.println("Something went wrong: " + e.getMessage());
}
}
}
```
#### Output
```
user@host bq_test % java -cp deps.jar:. BQExecuteSelectTest my-project us-east4 < test.sql
Jul 10, 2025 12:37:30 PM com.google.cloud.bigquery.ConnectionImpl getExecuteSelectResponse
INFO:
Using Fast Query Path
^C% <-- Hit Ctrl-C here after waiting for several minutes.
user@host bq_test %
```
#### External references such as API reference guides
- https://cloud.google.com/blog/topics/developers-practitioners/introducing-executeselect-client-library-method-and-how-use-it/
#### Any additional information below
When running a single command like this, you can simply Ctrl-C to end the process. But in a server environment where this could be running in different threads, it's very problematic. If a system (like mine) can allow interruption of ResultSet iteration (which can be necessary for very large result sets in specific scenarios), it can cause client threads to hang forever and never return, or background workers to wait forever and never become available to process other jobs.
Hướng dẫn đóng góp
Đánh giá
Issue này chưa được đánh giá.