googleapis / googleapis/google-cloud-java

[java-bigquery] [BigQuery] Thread will hang forever when using executeSelect if you do not iterate over the entire ResultSet

Abierto
#12,149 3 comentarios 0 reacciones 0 asignados Ver en GitHub
api: bigquery priority: p3 type: bug
Lenguaje dominante
Java
Estrellas
2.1k
Forks
1.2k
Merge medio
1 d 23 h
PR fusionados (30 d)
154

Descripción

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.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.