This commit is contained in:
lukaseder 2017-07-13 12:20:59 +02:00
parent 97b3c857d3
commit d4c391209c
3 changed files with 88 additions and 10 deletions

View File

@ -36,8 +36,13 @@ package org.jooq;
import java.sql.Statement;
import org.jooq.conf.Settings;
import org.jooq.conf.ThrowExceptions;
import org.jooq.exception.DataAccessException;
/**
* A type that contains either a {@link Result} or an update count.
* A type that contains either a {@link Result}, an update count, or an
* exception.
*
* @author Lukas Eder
*/
@ -57,4 +62,15 @@ public interface ResultOrRows {
* @see Statement#getUpdateCount()
*/
int rows();
/**
* The exception if applicable or <code>null</code> if there was no
* exception.
* <p>
* Exceptions are made available through this API only if
* {@link Settings#getThrowExceptions()} is set to
* {@link ThrowExceptions#THROW_NONE}. In all other cases, a batch execution
* is aborted and exceptions are thrown as ordinary Java exceptions.
*/
DataAccessException exception();
}

View File

@ -34,17 +34,54 @@
*/
package org.jooq;
import java.sql.SQLException;
import java.util.List;
import org.jooq.conf.Settings;
import org.jooq.conf.ThrowExceptions;
/**
* A list of {@link Result} and update counts that can be returned by
* {@link ResultQuery#fetchMany()} calls and other calls that produce multiple
* cursors and update counts.
* <p>
* For backwards-compatibility (e.g. with {@link ResultQuery#fetchMany()}), this
* type extends {@link List} containing only the {@link Result}, not the rows /
* update counts of interleaved updates. In order to get both, call
* {@link #resultsOrRows()}.
* type extends {@link List} containing only the {@link Result}, not the rows,
* update counts, exceptions of interleaved updates. In order to get them all,
* call {@link #resultsOrRows()} upon the results.
* <p>
* <h3>Exceptions</h3>
* <p>
* Some databases support raising several errors or exceptions per statement
* batch (e.g. {@link SQLDialect#SQLSERVER}):
* <p>
* <code><pre>
* 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);
* </pre></code>
* <p>
* The above batch will produce:
* <ul>
* <li>An update count (3)</li>
* <li>2 exceptions</li>
* <li>A result set</li>
* <li>1 exception</li>
* </ul>
* <p>
* By default (or when explicitly specifying {@link ThrowExceptions#THROW_ALL}
* in {@link Settings#getThrowExceptions()}), this particular batch will produce
* a single exception corresponding to <code>"message 1"</code>, with additional
* exceptions for <code>"message 2"</code> and <code>"message 3"</code> attached
* to {@link SQLException#getNextException()}, recursively.
* <p>
* When specifying {@link ThrowExceptions#THROW_FIRST}, only
* <code>"message 1"</code> is propagated. When specifying
* {@link ThrowExceptions#THROW_NONE}, then all exceptions are collected as
* results and are made available through {@link #resultsOrRows()} in
* {@link ResultOrRows#exception()}.
*
* @author Lukas Eder
*/

View File

@ -43,6 +43,7 @@ import org.jooq.Record;
import org.jooq.Result;
import org.jooq.ResultOrRows;
import org.jooq.Results;
import org.jooq.exception.DataAccessException;
/**
* @author Lukas Eder
@ -189,20 +190,22 @@ final class ResultsImpl extends AbstractList<Result<Record>> implements Results
static final class ResultOrRowsImpl implements ResultOrRows {
private final Result<Record> result;
private final int rows;
private final Result<Record> result;
private final int rows;
private final DataAccessException exception;
ResultOrRowsImpl(Result<Record> result) {
this(result, result != null ? result.size() : 0);
this(result, result != null ? result.size() : 0, null);
}
ResultOrRowsImpl(int rows) {
this(null, rows);
this(null, rows, null);
}
private ResultOrRowsImpl(Result<Record> result, int rows) {
private ResultOrRowsImpl(Result<Record> result, int rows, DataAccessException exception) {
this.result = result;
this.rows = rows;
this.exception = exception;
}
@Override
@ -215,11 +218,17 @@ final class ResultsImpl extends AbstractList<Result<Record>> implements Results
return rows;
}
@Override
public final DataAccessException exception() {
return exception;
}
@Override
public int hashCode() {
final int prime = 31;
int r = 1;
r = prime * r + ((this.result == null) ? 0 : this.result.hashCode());
r = prime * r + ((exception == null) ? 0 : exception.hashCode());
r = prime * r + ((result == null) ? 0 : result.hashCode());
r = prime * r + rows;
return r;
}
@ -233,6 +242,12 @@ final class ResultsImpl extends AbstractList<Result<Record>> implements Results
if (getClass() != obj.getClass())
return false;
ResultOrRowsImpl other = (ResultOrRowsImpl) obj;
if (exception == null) {
if (other.exception != null)
return false;
}
else if (!exception.equals(other.exception))
return false;
if (result == null) {
if (other.result != null)
return false;
@ -243,5 +258,15 @@ final class ResultsImpl extends AbstractList<Result<Record>> implements Results
return false;
return true;
}
@Override
public String toString() {
if (exception != null)
return exception.toString();
else if (result != null)
return result.toString();
else
return "" + rows;
}
}
}