java.sql2 DynamicMultiOperation with interlaced exceptions

Douglas Surber douglas.surber at oracle.com
Wed Oct 4 16:21:00 UTC 2017


Interlaced errors was not considered. It would be simple to add a Throwable as a third arg to ResultHandler.handle. Having two args of which one was always null is a bit of a hack. Three is definitely a hack. So I would eliminate ResultHandler and add the following methods to DynamicMultiOperation:

  public DynamicMultiOperation<T> onCount(BiConsumer<Integer, CountOperation<T>> handler);
  public DynamicMultiOperation<T> onRows(BiConsumer<Integer, RowOperation<T>> handler);
  public DynamicMultiOperation<T> onError(BiConsumer<Integer, Throwable> handler);

If there is no handler for a result the result is ignored or the Operation completes exceptionally. Not sure which would be better.

Douglas


> On Oct 4, 2017, at 2:22 AM, Lukas Eder <lukas.eder at gmail.com> wrote:
> 
> Hello,
> 
> The java.sql2 API contains a DynamicMultiOperation type which seems
> intended for use with statement batches or procedure calls that produce an
> unknown set of:
> 
> - Update counts
> - Result sets
> - Exceptions
> 
> Unfortunately, I'm missing the part where interlaced exceptions can be
> received. This may be SQL Server (and perhaps MySQL) specific, as I haven't
> really encountered this in any other databases. But in SQL Server, when
> running the following statement batch:
> 
> DECLARE @t TABLE(i INT);
> INSERT INTO @t VALUES (1),(2),(3);
> RAISERROR('message 1', 16, 2, 3);
> RAISERROR('message 2', 16, 2, 3);
> SELECT * FROM @t
> RAISERROR('message 3', 16, 2, 3);
> 
> We can run the following, complete program (taken from a blog post I've
> written recently [1]):
> 
> String sql = "DECLARE @t TABLE(i INT);\r\n" +
>    "INSERT INTO @t VALUES (1),(2),(3);\r\n" +
>    "RAISERROR('message 1', 16, 2, 3);\r\n" +
>    "RAISERROR('message 2', 16, 2, 3);\r\n" +
>    "SELECT * FROM @t\r\n" +
>    "RAISERROR('message 3', 16, 2, 3);";
> try (Connection c = new
> com.microsoft.sqlserver.jdbc.SQLServerDriver().connect(url, properties);
>     Statement s = c.createStatement()) {
> 
>    fetchLoop:
>        for (int i = 0, updateCount = 0; i < 256; i++) {
>            try {
>                boolean result = (i == 0)
>                    ? s.execute(sql)
>                    : s.getMoreResults();
> 
>                SQLWarning w = s.getWarnings();
>                for (int j = 0; j < 255 && w != null; j++) {
>                    System.out.println("Warning     : " + w.getMessage());
>                    w = w.getNextWarning();
>                }
> 
>                s.clearWarnings();
> 
>                if (result)
>                    try (ResultSet rs = s.getResultSet()) {
>                        System.out.println("Result      :");
>                        ResultSetMetaData m = rs.getMetaData();
> 
>                        while (rs.next())
>                            for (int col = 1; col <= m.getColumnCount();
> col++)
>                                System.out.println(
>                                    "  " + m.getColumnName(col) +
>                                    ": " + rs.getInt(col));
>                    }
>                else if ((updateCount = s.getUpdateCount()) != -1)
>                    System.out.println("Update Count: " + updateCount);
>                else
>                    break fetchLoop;
>                }
>            catch (SQLException e) {
>                System.out.println("Exception   : " + e.getMessage());
>            }
>        }
> }
> 
> 
> And get this result:
> 
> Update Count: 3
> Exception   : message 1
> Exception   : message 2
> Result      :
>  i: 1
>  i: 2
>  i: 3
> Exception   : message 3
> 
> I currently don't see a way how the exception messages "message 1" /
> "message 2" / "message 3" can be fetched through the DynamicMultiOperation.
> Could you perhaps show an example?
> 
> Thanks,
> Lukas
> 
> [1]:
> https://blog.jooq.org/2017/07/13/how-i-incorrectly-fetched-jdbc-resultsets-again/



More information about the jdbc-spec-discuss mailing list