public static void main(String[] args) throws Exception {
try (HikariDataSource dataSource = new HikariDataSource()) {
// configuring connection settings for Postgres
dataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/postgres"); // change to your Postgres connection settings
dataSource.setUsername("postgres"); // change to your Postgres connection settings
dataSource.setPassword("postgres"); // change to your Postgres connection settings
//
dataSource.setAutoCommit(false);
dataSource.setSchema("public");
dataSource.setMinimumIdle(1); // to be ensured we take the same connection from pool
dataSource.setMaximumPoolSize(1); // to be ensured we take the same connection from pool
// preparing for test (creating schema schema1 if not exists)
try (Connection connection = dataSource.getConnection()) {
connection.setSchema("schema1");
if (connection.getSchema() == null) {
try (PreparedStatement stm = connection.prepareStatement("create schema schema1")) {
stm.executeUpdate();
}
}
connection.setSchema("public");
connection.commit();
}
// start of test
try (Connection connection = dataSource.getConnection()) {
if (!"public".equals(connection.getSchema())) { // OK (skip if)
throw new AssertionError(connection.getSchema());
}
connection.setSchema("schema1");
if (!"schema1".equals(connection.getSchema())) { // OK (skip if)
throw new AssertionError(connection.getSchema());
}
connection.commit(); // Postgres save default schema in session scope on commit
connection.setSchema("public");
connection.rollback(); // Postgres restore default schema in session from last commit (schema1) but com.zaxxer.hikari.pool.ProxyConnection::dbschema is still equals to "public" schema
if ("public".equals(connection.getSchema())) { // OK (skip if) ProxyConnection.getSchema is directly calling Postgres connection getSchema() that is schema1 after rollback
throw new AssertionError(connection.getSchema());
}
} // while on close there is code in com.zaxxer.hikari.pool.PoolBase :
/*
// This if statement will be skipped case proxyConnection.getSchemaState() will return not actual schema from variable com.zaxxer.hikari.pool.ProxyConnection::dbschema, so schema in settings is equals to not actual value
if ((dirtyBits & 32) != 0 && this.schema != null && !this.schema.equals(proxyConnection.getSchemaState())) {
connection.setSchema(this.schema);
resetBits |= 32;
}
// proposed solution is to change call to proxyConnection.getSchemaState() to connection.getSchema()
// or may be needed to assign actual schema to com.zaxxer.hikari.pool.ProxyConnection::dbschema after rollback to make it sync (if default schema is specified in settings)
*/
try (Connection connection = dataSource.getConnection()) {
if (!"public".equals(connection.getSchema())) { // FAIL (execute if body) cause actual Postgres connection schema is "schema1" (it was not reset on previous ProxyConnection::close)
throw new AssertionError(connection.getSchema());
}
}
}
}
Reproduction code with explanations in comments: