result();
+
+ /**
+ * The update count if applicable, or the number of rows in
+ * {@link #result()}.
+ *
+ * @see Statement#getUpdateCount()
+ */
+ int rows();
+}
diff --git a/jOOQ/src/main/java/org/jooq/Results.java b/jOOQ/src/main/java/org/jooq/Results.java
index b730f6b2f8..ad1b589133 100644
--- a/jOOQ/src/main/java/org/jooq/Results.java
+++ b/jOOQ/src/main/java/org/jooq/Results.java
@@ -46,13 +46,41 @@ import java.util.List;
* 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.
+ *
+ * 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()}.
*
* @author Lukas Eder
*/
public interface Results extends List>, Attachable {
// ------------------------------------------------------------------------
- // Specialisations of Attachable methods
+ // XXX: Additional, Results-specific methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * All the results or update counts in their order as fetched via JDBC.
+ *
+ * While {@link #iterator()} and all the other methods inherited from the
+ * {@link List} API return the {@link Result} objects only, this method also
+ * includes update counts that may have occurred between two results.
+ *
+ * It can be safely assumed that:
+ *
+ * result.resultsOrRows()
+ * .stream()
+ * .filter(r -> r.result() != null)
+ * .map(r -> r.result())
+ * .collect(Collectors.toList())
+ * .equals(result);
+ *
+ */
+ List resultsOrRows();
+
+ // ------------------------------------------------------------------------
+ // XXX: Specialisations of Attachable methods
// ------------------------------------------------------------------------
/**
diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java
index 6b997c8628..a0470a76b3 100644
--- a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java
+++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java
@@ -104,7 +104,7 @@ abstract class AbstractResultQuery extends AbstractQuery imple
private transient boolean many;
private transient Cursor cursor;
private Result result;
- private Results results;
+ private ResultsImpl results;
// Some temp variables for String interning
private final Intern intern = new Intern();
diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java
index fa312fdbe8..c4414048b0 100644
--- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java
+++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java
@@ -119,7 +119,7 @@ public abstract class AbstractRoutine extends AbstractQueryPart implements Ro
private final List> outParameters;
private final DataType type;
private Parameter returnParameter;
- private Results results;
+ private ResultsImpl results;
private boolean overloaded;
private boolean hasDefaultedParameters;
diff --git a/jOOQ/src/main/java/org/jooq/impl/ResultsImpl.java b/jOOQ/src/main/java/org/jooq/impl/ResultsImpl.java
index 70f834afd1..394ef83456 100644
--- a/jOOQ/src/main/java/org/jooq/impl/ResultsImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/ResultsImpl.java
@@ -40,34 +40,42 @@
*/
package org.jooq.impl;
+import java.util.AbstractList;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
-import java.util.ListIterator;
import org.jooq.AttachableInternal;
import org.jooq.Configuration;
import org.jooq.Record;
import org.jooq.Result;
+import org.jooq.ResultOrRows;
import org.jooq.Results;
/**
* @author Lukas Eder
*/
-class ResultsImpl implements Results, AttachableInternal {
+class ResultsImpl extends AbstractList> implements Results, AttachableInternal {
/**
* Generated UID
*/
- private static final long serialVersionUID = 1744826140354980500L;
+ private static final long serialVersionUID = 1744826140354980500L;
- private Configuration configuration;
- private final List> results;
+ private Configuration configuration;
+ private final List results;
ResultsImpl(Configuration configuration) {
this.configuration = configuration;
- this.results = new ArrayList>();
+ this.results = new ArrayList();
+ }
+
+ // ------------------------------------------------------------------------
+ // XXX: Additional, Results-specific methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public final List resultsOrRows() {
+ return results;
}
// -------------------------------------------------------------------------
@@ -78,7 +86,7 @@ class ResultsImpl implements Results, AttachableInternal {
public final void attach(Configuration c) {
this.configuration = c;
- for (Result> result : results)
+ for (Result> result : this)
if (result != null)
result.attach(c);
}
@@ -100,11 +108,13 @@ class ResultsImpl implements Results, AttachableInternal {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
-
String separator = "";
- for (Result> result : this) {
- sb.append(separator)
- .append(result);
+
+ for (ResultOrRows result : results) {
+ if (result.result() == null)
+ sb.append(separator).append("Update count: ").append(result.rows());
+ else
+ sb.append(separator).append("Result set:\n").append(result.result());
separator = "\n";
}
@@ -137,116 +147,103 @@ class ResultsImpl implements Results, AttachableInternal {
@Override
public final int size() {
- return results.size();
- }
-
- @Override
- public final boolean isEmpty() {
- return results.isEmpty();
- }
-
- @Override
- public final boolean contains(Object o) {
- return results.contains(o);
- }
-
- @Override
- public final Iterator> iterator() {
- return results.iterator();
- }
-
- @Override
- public final Object[] toArray() {
- return results.toArray();
- }
-
- @Override
- public final T[] toArray(T[] a) {
- return results.toArray(a);
- }
-
- @Override
- public final boolean add(Result e) {
- return results.add(e);
- }
-
- @Override
- public final boolean remove(Object o) {
- return results.remove(o);
- }
-
- @Override
- public final boolean containsAll(Collection> c) {
- return results.containsAll(c);
- }
-
- @Override
- public final boolean addAll(Collection extends Result> c) {
- return results.addAll(c);
- }
-
- @Override
- public final boolean addAll(int index, Collection extends Result> c) {
- return results.addAll(index, c);
- }
-
- @Override
- public final boolean removeAll(Collection> c) {
- return results.removeAll(c);
- }
-
- @Override
- public final boolean retainAll(Collection> c) {
- return results.retainAll(c);
- }
-
- @Override
- public final void clear() {
- results.clear();
+ return list().size();
}
@Override
public final Result get(int index) {
- return results.get(index);
+ return list().get(index);
}
@Override
- public final Result set(int index, Result element) {
- return results.set(index, element);
+ public Result set(int index, Result element) {
+ return results.set(translatedIndex(index), new ResultOrRowsImpl(element)).result();
}
@Override
- public final void add(int index, Result element) {
- results.add(index, element);
+ public void add(int index, Result element) {
+ results.add(translatedIndex(index), new ResultOrRowsImpl(element));
}
@Override
- public final Result remove(int index) {
- return results.remove(index);
+ public Result remove(int index) {
+ return results.remove(translatedIndex(index)).result();
}
- @Override
- public final int indexOf(Object o) {
- return results.indexOf(o);
+ private final List> list() {
+ List> list = new ArrayList>();
+
+ for (ResultOrRows result : results)
+ if (result.result() != null)
+ list.add(result.result());
+
+ return list;
}
- @Override
- public final int lastIndexOf(Object o) {
- return results.lastIndexOf(o);
+ private final int translatedIndex(int index) {
+ int translated = 0;
+
+ for (int i = 0; i < index; i++)
+ while (results.get(translated++).result() == null);
+
+ return translated;
}
- @Override
- public final ListIterator> listIterator() {
- return results.listIterator();
- }
+ static final class ResultOrRowsImpl implements ResultOrRows {
- @Override
- public final ListIterator> listIterator(int index) {
- return results.listIterator(index);
- }
+ private final Result result;
+ private final int rows;
- @Override
- public final List> subList(int fromIndex, int toIndex) {
- return results.subList(fromIndex, toIndex);
+ ResultOrRowsImpl(Result result) {
+ this(result, result != null ? result.size() : 0);
+ }
+
+ ResultOrRowsImpl(int rows) {
+ this(null, rows);
+ }
+
+ private ResultOrRowsImpl(Result result, int rows) {
+ this.result = result;
+ this.rows = rows;
+ }
+
+ @Override
+ public final Result result() {
+ return result;
+ }
+
+ @Override
+ public final int rows() {
+ return rows;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int r = 1;
+ r = prime * r + ((this.result == null) ? 0 : this.result.hashCode());
+ r = prime * r + rows;
+ return r;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ResultOrRowsImpl other = (ResultOrRowsImpl) obj;
+ if (result == null) {
+ if (other.result != null)
+ return false;
+ }
+ else if (!result.equals(other.result))
+ return false;
+ if (rows != other.rows)
+ return false;
+ return true;
+ }
}
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/Utils.java b/jOOQ/src/main/java/org/jooq/impl/Utils.java
index 285c5d0dca..0b8203e468 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Utils.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Utils.java
@@ -2523,6 +2523,7 @@ final class Utils {
static void consumeResultSets(ExecuteContext ctx, ExecuteListener listener, Results results, Intern intern) throws SQLException {
boolean anyResults = false;
int i = 0;
+ int rows = (ctx.resultSet() == null) ? ctx.statement().getUpdateCount() : 0;
for (i = 0; i < maxConsumedResults; i++) {
if (ctx.resultSet() != null) {
@@ -2530,12 +2531,18 @@ final class Utils {
Field>[] fields = new MetaDataFieldProvider(ctx.configuration(), ctx.resultSet().getMetaData()).getFields();
Cursor c = new CursorImpl(ctx, listener, fields, intern != null ? intern.internIndexes(fields) : null, true, false);
- results.add(c.fetch());
+ results.resultsOrRows().add(new ResultsImpl.ResultOrRowsImpl(c.fetch()));
+ }
+ else {
+ if (rows != -1)
+ results.resultsOrRows().add(new ResultsImpl.ResultOrRowsImpl(rows));
+ else
+ break;
}
if (ctx.statement().getMoreResults())
ctx.resultSet(ctx.statement().getResultSet());
- else if (ctx.statement().getUpdateCount() != -1)
+ else if ((rows = ctx.statement().getUpdateCount()) != -1)
ctx.resultSet(null);
else
break;