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

No one assigned

    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