如何在执行JDBC语句时收集警告/通知?

Bor*_*lev 5 java postgresql jdbc postgresql-9.4

我遇到了最新版PostgreSQL JDBC驱动程序的问题:在准备好的语句仍在执行时,我无法收集警告/通知.警告列表仅在语句返回后变为可用.

我使用此功能与一些以前的驱动程序版本(我猜9.1),但PgPreparedStatement从那时起实施可能已经改变.

在返回结果之前,我有哪些选择来收集警告?

我创建了这个简单的测试:

public class WarningTest {

    @Test
    public void readWarnings() throws Exception {
        Connection con = DriverManager.getConnection("jdbc:postgresql://localhost:5432/test_db", "test_user", "test_password");
        createTestFunction(con);

        PreparedStatement statement = con.prepareStatement("SELECT test_function();");
        SQLWarning[] warnings = new SQLWarning[1];
        new Timer().schedule(new TimerTask() {
            @Override public void run() {
                try {
                    warnings[0] = statement.getWarnings();
                } catch (SQLException e) {
                    Assert.fail("Exception thrown: " + e.getMessage());
                }
            }
        }, 3500);
        statement.executeQuery();
        Thread.sleep(1000);
        statement.close();

        Assert.assertNotNull(warnings[0]);
        Assert.assertFalse(warnings[0].getMessage().isEmpty());
    }

    private void createTestFunction(Connection con) throws SQLException {
        final PreparedStatement statement = con.prepareStatement(
            "CREATE OR REPLACE FUNCTION test_function() RETURNS VOID AS\n"
            + "$BODY$\n"
            + "BEGIN\n"
            + "\tFOR i IN 1..3 LOOP \n"
            + "\t\tRAISE NOTICE 'Tick %', i;\n"
            + "\t\tEXECUTE pg_sleep(1);\n"
            + "\tEND LOOP;\n"
            + "END\n"
            + "$BODY$\n"
            + "\tLANGUAGE plpgsql STABLE;");
        statement.execute();
        statement.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

它创建一个运行3秒的函数,并在每秒开始时写一个勾号.

在返回结果后,测试通过这样的计时器.但是,如果您将计时器延迟从减少35001500测试将失败,即使数据库在那时发出了2个通知.

Mag*_*nus 7

这个问题是按照预期在REL9.4.1210版本REL9.4.1209和以下工作中引入的.

这个提交的第244行是为什么它不再起作用的原因,警告一旦被收到就会立即直接添加到声明中,但它被重新计算,现在它们仅在完成后才可用.

我为此提出了一个问题,以及解决它公关问题.