Skip to content

[jdbc-v2] Connection#getNetworkTimeout, getCatalog and setClientInfo do not throw on a closed connection #3270

Closed

Description

@polyglotAI-bot

Description

In jdbc-v2, some Connection methods do not check if the connection is closed. After close(), these methods return normally:

  • getNetworkTimeout() returns a value.
  • getCatalog() returns null.
  • setClientInfo(String, String) and setClientInfo(Properties) return normally. setClientInfo("ApplicationName", …) also calls config.updateUserClient(value, client) on the closed client.
  • With jdbc_ignore_unsupported_values=true, commit() and rollback() return normally.

The java.sql.Connection javadoc for each of these methods says that it throws SQLException (SQLClientInfoException for setClientInfo) "if this method is called on a closed connection". Most other methods in the same class do this: getSchema(), getAutoCommit(), getClientInfo(String), setNetworkTimeout(...) throw SQLException: Connection is closed (SQLState 08000). The jdbc v1 driver also checks: ClickHouseConnectionImpl#getNetworkTimeout() calls ensureOpen().

Code that uses the exception to find a dead connection does not get it from these methods.

Root cause

jdbc-v2/src/main/java/com/clickhouse/jdbc/ConnectionImpl.java (main 771b8bcca, same code in v0.11.0). These methods do not call ensureOpen() (line 757):

  • getNetworkTimeout(), line 737
  • getCatalog(), line 337
  • setClientInfo(String, String), line 576, and setClientInfo(Properties), line 585
  • commit(), line 286, and rollback(), line 291. They only call featureManager.unsupportedFeatureThrow(...), which does nothing when jdbc_ignore_unsupported_values=true.

Suggested fix

Call ensureOpen() first in each of these methods.

  • setClientInfo can only throw SQLClientInfoException. Thus it must convert the closed check into SQLClientInfoException (for example, new SQLClientInfoException("Connection is closed", ExceptionUtils.SQL_STATE_CONNECTION_EXCEPTION, Collections.emptyMap())). setClientInfo(Properties) can do the check one time before its loops.
  • In commit() / rollback(), call ensureOpen() before unsupportedFeatureThrow.
  • Keep the current behavior of these methods, which the javadoc allows on a closed connection: close() and abort(...) do nothing a second time, isClosed() returns true, and isValid(...) returns false.
  • On an open connection, behavior does not change.

Note: open PR #3266 (for #3260) changes the body of getNetworkTimeout(). It does not add the closed check. The two changes touch the same method.

Steps to reproduce

  1. Open a jdbc-v2 connection.
  2. Call close().
  3. Call getNetworkTimeout(), getCatalog(), or setClientInfo("ApplicationName", "x").

Error Log or Exception StackTrace

Output of the code example below (server 26.9.1.1629, main 771b8bcca):

== defaults; server version 26.9.1.1629
 after close(), isClosed()=true:
  getNetworkTimeout() -> returned 0   (NO EXCEPTION)
  getCatalog() -> returned null   (NO EXCEPTION)
  setClientInfo(ApplicationName, x) -> returned void   (NO EXCEPTION)
  setClientInfo(Properties) -> returned void   (NO EXCEPTION)
  commit() -> threw SQLFeatureNotSupportedException: commit() is not supported. [SQLState=0A000]
  rollback() -> threw SQLFeatureNotSupportedException: rollback() is not supported. [SQLState=0A000]
 contrast (methods that check):
  getSchema() -> threw SQLException: Connection is closed [SQLState=08000]
  getAutoCommit() -> threw SQLException: Connection is closed [SQLState=08000]
  getClientInfo(ApplicationName) -> threw SQLException: Connection is closed [SQLState=08000]
  setNetworkTimeout(exec, 1000) -> threw SQLException: Connection is closed [SQLState=08000]
  isValid(1) -> returned false   (NO EXCEPTION)
== jdbc_ignore_unsupported_values=true; server version 26.9.1.1629
 after close(), isClosed()=true:
  getNetworkTimeout() -> returned 0   (NO EXCEPTION)
  getCatalog() -> returned null   (NO EXCEPTION)
  setClientInfo(ApplicationName, x) -> returned void   (NO EXCEPTION)
  setClientInfo(Properties) -> returned void   (NO EXCEPTION)
  commit() -> returned void   (NO EXCEPTION)
  rollback() -> returned void   (NO EXCEPTION)

The result is the same with socket_timeout=30000.

Expected Behaviour

After close(), getNetworkTimeout(), getCatalog(), commit() and rollback() throw SQLException ("Connection is closed", SQLState 08000), the same as getSchema() and setNetworkTimeout(...). Both setClientInfo overloads throw SQLClientInfoException. This is what the java.sql.Connection javadoc says, for example for getNetworkTimeout():

Throws: SQLException - if a database access error occurs or this method is called on a closed Connection

Code Example

Properties p = new Properties();
p.setProperty("user", "default");
p.setProperty("password", "<password>");
Connection c = new com.clickhouse.jdbc.Driver().connect("jdbc:clickhouse://localhost:8123/default", p);
c.close();

c.getNetworkTimeout();                    // returns 0, expected SQLException
c.getCatalog();                           // returns null, expected SQLException
c.setClientInfo("ApplicationName", "x");  // returns normally, expected SQLClientInfoException
c.getSchema();                            // throws SQLException: Connection is closed (correct)

Configuration

Client Configuration

// defaults; also tested with socket_timeout=30000 and jdbc_ignore_unsupported_values=true

Environment

  • Cloud
  • Client version: jdbc-v2 from main at 771b8bcca (0.12.0-rc1-SNAPSHOT). The code is the same in v0.11.0.
  • Language version: OpenJDK 17
  • OS: Linux (Docker)

ClickHouse Server

  • ClickHouse Server version: 26.9.1.1629
  • ClickHouse Server non-default settings, if any: none that apply
  • CREATE TABLE statements for tables involved: none
  • Sample data for all these tables: none

Found by automated analysis of the client (Polyglot AI) while working on #3260. Verified against a live server, not only by reading the code.

Activity

  1. added a commit that references this issue on Nov 6, 2026
    f4a1a71
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions