Message-ID: From: "manav-yb (@manav-yb)" To: "pgjdbc/pgjdbc" Date: Sun, 07 Dec 2025 14:18:09 +0000 Subject: [pgjdbc/pgjdbc] issue #3889: JDBC Not Sending CLOSE packet List-Id: X-GitHub-Author-Id: 36265791 X-GitHub-Author-Login: manav-yb X-GitHub-Issue: 3889 X-GitHub-Repo: pgjdbc/pgjdbc X-GitHub-State: closed X-GitHub-Type: issue X-GitHub-Url: https://github.com/pgjdbc/pgjdbc/issues/3889 Content-Type: text/plain; charset=utf-8 Please read https://stackoverflow.com/help/minimal-reproducible-example **Describe the issue** Wrote an JDBC application which uses extended protocol level prepared statements. And using pstmt.close() to deallocate the same prep stmt. But in my server logs I don't see CLOSE packet been sent by driver. **Driver Version?** postgresql-42.7.1.jar **Java Version?** javac 1.8.0_29 **OS Version?** **PostgreSQL Version?** PG-15. **To Reproduce** Create a table in any database/user. CREATE TABLE T_(A INT, B INT); Run the below application. **Expected behaviour** Expectation is i should get CLOSE packet and prepared statement (`S_1 insert into t_ values ($1, $2)`) should not comes in pg_prepared_statements table after calling pstmt1.close. What i see is that: prepared statement (S_1 insert into t_ values ($1, $2)) comes even after calling pstmt1.close(). **Logs** If possible PostgreSQL logs surrounding the occurrence of the issue Additionally logs from the driver can be obtained adding Using the following template code make sure the bug can be replicated in the driver alone. ``` import java.sql.*; public class sendClose3 { public static void main(String[] args) { Connection connection = null; PreparedStatement pstmt1 = null, pstmt2 = null; try { // prepareThreshold=1 is crucial here connection = DriverManager.getConnection("jdbc:postgresql://10.150.3.175:5433/yugabyte?prepareThreshold=1", "yugabyte","yugabyte"); // --------------------------------------------------------- // CHANGE 1: Use placeholders (?) // This forces the driver to use Extended Query Protocol (Parse/Bind) // and create a named statement (e.g., "S_1") on the server. // --------------------------------------------------------- pstmt1 = connection.prepareStatement("insert into t_ values (?, ?)"); pstmt1.setInt(1, 1); pstmt1.setInt(2, 2); // Execute twice to ensure the driver switches to server-prepare mode pstmt1.execute(); pstmt1.execute(); pstmt1.execute(); pstmt1.execute(); pstmt1.execute(); pstmt1.execute(); pstmt1.execute(); pstmt1.execute(); pstmt1.execute(); pstmt1.execute(); // --------------------------------------------------------- // CHANGE 2: Close the statement // The driver now marks "S_1" as closed internally and queues the packet. // --------------------------------------------------------- Statement stmt = connection.createStatement(); System.out.println("Before closing prepared statement"); ResultSet rs = stmt.executeQuery("select name, statement from pg_prepared_statements"); while (rs.next()) { System.out.println(rs.getString("name") + " " + rs.getString("statement")); } rs.close(); // stmt.close(); pstmt1.close(); System.out.println("After closing prepared statement"); rs = stmt.executeQuery("select name, statement from pg_prepared_statements"); while (rs.next()) { System.out.println(rs.getString("name") + " " + rs.getString("statement")); } rs.close(); stmt.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); } } } ```