Skip to content

[Java] Invocation of close method from ArrowFlightConnection throws a SQLException when using catalog as parameter #66

Open
@scruz-denodo

Description

@scruz-denodo

Describe the bug, including details regarding any error messages, version, and platform.

Affected version
flight-sql-jdbc-driver version 17.0.0

Description

With flight-sql-jdbc-driver version 17 the method org.apache.arrow.driver.jdbc.ArrowFlightConnection#close returns a SQLException when the connection has defined a value for catalog parameter.

I was testing this change and I am facing a problem when the java.sql.Connection#close method of the JDBC connection is called.

I am receiving the following error invoking the method.

Exception in thread "main" java.sql.SQLException: UNKNOWN: Uncaught exception in the SynchronizationContext. Re-thrown.
	at org.apache.calcite.avatica.Helper.createException(Helper.java:56)
	at org.apache.calcite.avatica.Helper.createException(Helper.java:41)
	at org.apache.arrow.driver.jdbc.ArrowFlightConnection.close(ArrowFlightConnection.java:187)
	at com.arrowflight.test.Main.test7(Main.java:249)
	at com.arrowflight.test.Main.main(Main.java:27)
Caused by: io.grpc.StatusRuntimeException: UNKNOWN: Uncaught exception in the SynchronizationContext. Re-thrown.
	at io.grpc.Status.asRuntimeException(Status.java:525)
	at io.grpc.internal.RetriableStream$1.uncaughtException(RetriableStream.java:75)
	at io.grpc.SynchronizationContext.drain(SynchronizationContext.java:96)
	at io.grpc.SynchronizationContext.execute(SynchronizationContext.java:126)
	at io.grpc.internal.RetriableStream.safeCloseMasterListener(RetriableStream.java:838)
	at io.grpc.internal.RetriableStream.cancel(RetriableStream.java:531)
	at io.grpc.internal.RetriableStream.start(RetriableStream.java:393)
	at io.grpc.internal.ClientCallImpl.startInternal(ClientCallImpl.java:285)
	at io.grpc.internal.ClientCallImpl.start(ClientCallImpl.java:184)
	at io.grpc.ForwardingClientCall.start(ForwardingClientCall.java:32)
	at org.apache.arrow.flight.grpc.ClientInterceptorAdapter$FlightClientCall.start(ClientInterceptorAdapter.java:142)
	at io.grpc.ForwardingClientCall.start(ForwardingClientCall.java:32)
	at io.grpc.stub.MetadataUtils$HeaderAttachingClientInterceptor$HeaderAttachingClientCall.start(MetadataUtils.java:75)
	at io.grpc.stub.ClientCalls.startCall(ClientCalls.java:335)
	at io.grpc.stub.ClientCalls.asyncUnaryRequestCall(ClientCalls.java:311)
	at io.grpc.stub.ClientCalls.blockingServerStreamingCall(ClientCalls.java:210)
	at org.apache.arrow.flight.impl.FlightServiceGrpc$FlightServiceBlockingStub.doAction(FlightServiceGrpc.java:874)
	at org.apache.arrow.flight.FlightClient.doAction(FlightClient.java:168)
	at org.apache.arrow.flight.FlightClient.closeSession(FlightClient.java:686)
	at org.apache.arrow.flight.sql.FlightSqlClient.closeSession(FlightSqlClient.java:998)
	at org.apache.arrow.driver.jdbc.client.ArrowFlightSqlClientHandler.close(ArrowFlightSqlClientHandler.java:224)
	at org.apache.arrow.util.AutoCloseables.close(AutoCloseables.java:97)
	at org.apache.arrow.util.AutoCloseables.close(AutoCloseables.java:75)
	at org.apache.arrow.driver.jdbc.ArrowFlightConnection.close(ArrowFlightConnection.java:181)
	... 2 more
Caused by: java.util.concurrent.RejectedExecutionException: Task io.grpc.internal.SerializingExecutor@6ecdbab8 rejected from java.util.concurrent.ThreadPoolExecutor@3dd4a6fa[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 25]
	at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
	at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825)
	at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355)
	at io.grpc.internal.SerializingExecutor.schedule(SerializingExecutor.java:102)
	at io.grpc.internal.SerializingExecutor.execute(SerializingExecutor.java:95)
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.closedInternal(ClientCallImpl.java:736)
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.closed(ClientCallImpl.java:680)
	at io.grpc.internal.RetriableStream$4.run(RetriableStream.java:843)
	at io.grpc.SynchronizationContext.drain(SynchronizationContext.java:94)
	... 23 more

I think the reason is the following. Checking this code:

https://github.com/apache/arrow/blob/6a2e19a852b367c72d7b12da4d104456491ed8b7/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java#L174-L189

https://github.com/apache/arrow/blob/6a2e19a852b367c72d7b12da4d104456491ed8b7/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java#L174-L189

I think that line line 181 from org.apache.arrow.driver.jdbc.ArrowFlightConnection#close should be remove for avoding the problem. The close is already done at 175.

Also, I would remove the is if:
https://github.com/apache/arrow/blob/6a2e19a852b367c72d7b12da4d104456491ed8b7/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java#L222-L225
why not invoking the closeSession when the catalog was not set?

It can be reproducible with this code:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class CloseIssue {
    private static final String URL = "jdbc:arrow-flight-sql://localhost:9994?catalog=mydatabase&useEncryption=0";

    public static void main(String[] args) throws Exception {
        Class.forName("org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver");
        try (Connection conn = DriverManager.getConnection(URL, "admin", "admin")) {
            try (PreparedStatement pst = conn.prepareStatement("select 1");
                 ResultSet rs = pst.executeQuery()) {
                ResultSetMetaData rsm = rs.getMetaData();
                for (int i = 1; i <= rsm.getColumnCount(); i++) {
                    System.out.print(rsm.getColumnName(i) + " (" + rsm.getColumnType(i) + ") ");
                }
            }
        }
    }
}

This problems does not happen with prior versions, so it can be considered a regression.

Component(s)

Java

Metadata

Metadata

Assignees

Labels

Type: bugSomething isn't workinghelp wantedExtra attention is needed

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions