Skip to content

Pgpool closes the frontend for extended-protocol DISCARD ALL #175

Description

@apkipa

Pgpool-II version

4.8devel (1a873669), backend_clustering_mode = raw, connection_cache = on, one configured PostgreSQL node.

Description

In raw mode, an extended-protocol DISCARD ALL succeeds on direct PostgreSQL but causes Pgpool to close the frontend connection.

The same failure is reachable from an ordinary PgJDBC 42.7.7 Statement.execute("DISCARD ALL") call: its default preferQueryMode=extended selects this path. No PreparedStatement or pipeline is required; preferQueryMode=simple avoids the failure.

CommandComplete() processes the command before forwarding its completion. Its DISCARD ALL branch calls pool_clear_sent_message_list(). Clearing the final sent message destroys its query context through pool_sent_message_destroy(), and pool_query_context_destroy() sets the session query context to NULL. CommandComplete() then calls pool_set_query_state(), whose null-context check (CHECK_QUERY_CONTEXT_IS_VALID) raises the local error.

Reproduce

Start PostgreSQL 16 and Pgpool-II in the configuration above, download postgresql-42.7.7.jar, and run:

javac -cp postgresql-42.7.7.jar reproduce.java
java -cp .:postgresql-42.7.7.jar Reproduce <direct-jdbc-url> <pgpool-jdbc-url>
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

class Reproduce {
  static void run(String label, String url) {
    Connection c = null;
    try {
      c = DriverManager.getConnection(url);
      try (Statement s = c.createStatement()) {
        s.execute("DISCARD ALL");
        try (ResultSet r = s.executeQuery("SELECT 99")) {
          r.next();
          System.out.println(label + ": " + r.getInt(1));
        }
      }
    } catch (SQLException e) {
      boolean closed = false;
      if (c != null) {
        try { closed = c.isClosed(); } catch (SQLException ignored) { closed = true; }
      }
      System.out.println(label + ": " + e.getClass().getSimpleName() + ": "
          + e.getMessage().split("\\R", 2)[0] + "; closed=" + closed);
    } finally {
      if (c != null) {
        try { c.close(); } catch (SQLException ignored) { }
      }
    }
  }

  public static void main(String[] args) {
    run("direct", args[0]);
    run("pgpool", args[1]);
  }
}

Expected behavior

Both endpoints should complete DISCARD ALL, remain usable, and print:

direct: 99
pgpool: 99

Actual behavior

The reproducer prints:

direct: 99
pgpool: PSQLException: ERROR: setting db node for query to be sent, no query context; closed=true

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions