JDK-8188051-branch updates JDK-8188051-branch
authorlancea
Wed, 20 Jun 2018 15:38:40 -0400
branchJDK-8188051-branch
changeset 56797 fb523d4d9185
parent 56796 69b384805d61
child 56798 3b438b3fef46
JDK-8188051-branch updates
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaConnectionProperty.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaType.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ArrayCountOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ArrayRowCountOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Connection.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSource.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSourceFactory.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Examples.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/MultiOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OutOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowCountOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowPublisherOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/PrimitiveOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowCountOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowProcessorOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowPublisherOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ShardingKey.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlArray.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlBlob.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlClob.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlColumns.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlException.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlParameter.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlRef.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlStruct.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlType.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Submission.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Transaction.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/TransactionOutcome.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaConnectionProperty.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaConnectionProperty.java	Wed Jun 20 15:38:40 2018 -0400
@@ -33,6 +33,10 @@
 /**
  * A set of {@link ConnectionProperty}  commonly supported. Implementations are not
  * required to support all of these properties.
+ * 
+ * ISSUE: Need others such as IDLE_TIMEOUT, TIME_TO_LIVE_TIMEOUT, etc. Can we
+ * get away with just ConnectionProperties or do we need DataSourceProperties
+ * as well, MAX_CACHED_CONNECTIONS, etc?
  *
  */
 public enum AdbaConnectionProperty implements ConnectionProperty {
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaType.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaType.java	Wed Jun 20 15:38:40 2018 -0400
@@ -25,6 +25,13 @@
 
 package jdk.incubator.sql2;
 
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+
 /**
  * <P>Defines the constants that are used to identify generic
  * SQL types, called JDBC types.
@@ -37,168 +44,172 @@
         /**
      * Identifies the generic SQL type {@code BIT}.
      */
-    BIT,
+    BIT(Boolean.class),
     /**
      * Identifies the generic SQL type {@code TINYINT}.
      */
-    TINYINT,
+    TINYINT(Byte.class),
     /**
      * Identifies the generic SQL type {@code SMALLINT}.
      */
-    SMALLINT,
+    SMALLINT(Short.class),
     /**
      * Identifies the generic SQL type {@code INTEGER}.
      */
-    INTEGER,
+    INTEGER(Integer.class),
     /**
      * Identifies the generic SQL type {@code BIGINT}.
      */
-    BIGINT,
+    BIGINT(Long.class),
     /**
      * Identifies the generic SQL type {@code FLOAT}.
      */
-    FLOAT,
+    FLOAT(Double.class),
     /**
      * Identifies the generic SQL type {@code REAL}.
      */
-    REAL,
+    REAL(Float.class),
     /**
      * Identifies the generic SQL type {@code DOUBLE}.
      */
-    DOUBLE,
+    DOUBLE(Double.class),
     /**
      * Identifies the generic SQL type {@code NUMERIC}.
      */
-    NUMERIC,
+    NUMERIC(BigDecimal.class),
     /**
      * Identifies the generic SQL type {@code DECIMAL}.
      */
-    DECIMAL,
+    DECIMAL(BigDecimal.class),
     /**
      * Identifies the generic SQL type {@code CHAR}.
      */
-    CHAR,
+    CHAR(String.class),
     /**
      * Identifies the generic SQL type {@code VARCHAR}.
      */
-    VARCHAR,
+    VARCHAR(String.class),
     /**
      * Identifies the generic SQL type {@code LONG VARCHAR}.
      */
-    LONG_VARCHAR,
+    LONG_VARCHAR(String.class),
     /**
      * Identifies the generic SQL type {@code DATE}.
      */
-    DATE,
+    DATE(LocalDate.class),
     /**
      * Identifies the generic SQL type {@code TIME}.
      */
-    TIME,
+    TIME(LocalTime.class),
     /**
      * Identifies the generic SQL type {@code TIMESTAMP}.
      */
-    TIMESTAMP,
+    TIMESTAMP(LocalDateTime.class),
     /**
      * Identifies the generic SQL type {@code BINARY}.
      */
-    BINARY,
+    BINARY(byte[].class),
     /**
      * Identifies the generic SQL type {@code VARBINARY}.
      */
-    VARBINARY,
+    VARBINARY(byte[].class),
     /**
      * Identifies the generic SQL type {@code LONG VARBINARY}.
      */
-    LONG_VARBINARY,
+    LONG_VARBINARY(byte[].class),
     /**
      * Identifies the generic SQL value {@code NULL}.
      */
-    NULL,
+    NULL(Void.class),
     /**
      * Indicates that the SQL type
      * is database-specific and gets mapped to a Java object that can be
      * accessed via the methods getObject and setObject.
      */
-    OTHER,
+    OTHER(Object.class),
     /**
      * Indicates that the SQL type
      * is database-specific and gets mapped to a Java object that can be
      * accessed via the methods getObject and setObject.
      */
-    JAVA_OBJECT,
+    JAVA_OBJECT(Object.class),
     /**
      * Identifies the generic SQL type {@code DISTINCT}.
      */
-    DISTINCT,
+    DISTINCT(Object.class),
     /**
      * Identifies the generic SQL type {@code STRUCT}.
      */
-    STRUCT,
+    STRUCT(SqlStruct.class),
     /**
      * Identifies the generic SQL type {@code ARRAY}.
      */
-    ARRAY,
+    ARRAY(Object[].class), //TODO questionable. really want <?>[]
     /**
      * Identifies the generic SQL type {@code BLOB}.
      */
-    BLOB,
+    BLOB(SqlBlob.class),
     /**
      * Identifies the generic SQL type {@code CLOB}.
      */
-    CLOB,
+    CLOB(SqlClob.class),
     /**
      * Identifies the generic SQL type {@code REF}.
      */
-    REF,
+    REF(SqlRef.class),
     /**
      * Identifies the generic SQL type {@code DATALINK}.
      */
-    DATALINK,
+    DATALINK(Void.class), //TODO
     /**
      * Identifies the generic SQL type {@code BOOLEAN}.
      */
-    BOOLEAN,
-
+    BOOLEAN(Boolean.class),
     /**
      * Identifies the SQL type {@code ROWID}.
      */
-    ROWID,
+    ROWID(Void.class), //TODO
     /**
      * Identifies the generic SQL type {@code NCHAR}.
      */
-    NCHAR,
+    NCHAR(String.class),
     /**
      * Identifies the generic SQL type {@code NVARCHAR}.
      */
-    NVARCHAR,
+    NVARCHAR(String.class),
     /**
      * Identifies the generic SQL type {@code LONG NVARCHAR}.
      */
-    LONG_NVARCHAR,
+    LONG_NVARCHAR(String.class),
     /**
      * Identifies the generic SQL type {@code NCLOB}.
      */
-    NCLOB,
+    NCLOB(SqlClob.class),
     /**
      * Identifies the generic SQL type {@code SQLXML}.
      */
-    SQLXML,
+    SQLXML(Void.class), //TODO
 
     /**
      * Identifies the generic SQL type {@code REF CURSOR}.
      */
-    REF_CURSOR,
+    REF_CURSOR(Void.class), //TODO
 
     /**
      * Identifies the generic SQL type {@code TIME WITH TIME ZONE}.
      */
-    TIME_WITH_TIME_ZONE,
+    TIME_WITH_TIME_ZONE(OffsetTime.class),
 
     /**
      * Identifies the generic SQL type {@code TIMESTAMP WITH TIME ZONE}.
      */
-    TIMESTAMP_WITH_TIME_ZONE;
+    TIMESTAMP_WITH_TIME_ZONE(OffsetDateTime.class);
 
+  protected final Class javaType;
+  
+  AdbaType(Class type) {
+    javaType = type;
+  }
   
     /**
      *{@inheritDoc }
@@ -229,4 +240,9 @@
     throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   }
   
+  @Override
+  public <T> Class<T> getJavaType() {
+    return javaType;
+  }
+  
 }
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ArrayCountOperation.java	Wed Jun 20 15:12:52 2018 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.incubator.sql2;
-
-import java.time.Duration;
-import java.util.List;
-import java.util.concurrent.CompletionStage;
-import java.util.function.Consumer;
-import java.util.stream.Collector;
-
-/**
- * A database operation that returns a count that is executed multiple times
- * with multiple sets of parameter values in one database operation. The
- * parameters are submitted to the database in the same order as in the
- * sequences passed to the set methods. The count results are passed to the
- * collector in the same order they are produced by the database. The
- * value of the Operation is the final result produced by the collector.
- *
- * @param <T> the type of the result of collecting the counts
- */
-public interface ArrayCountOperation<T> extends Operation<T> {
-
-  /**
-   * Set a sequence of parameter values. The value is captured and should not be
-   * modified before the {@link Operation} is completed.
-   *
-   * The Operation is completed exceptionally with ClassCastException if any of
-   * the values cannot be converted to the specified SQL type.
-   *
-   * @param id the identifier of the parameter marker to be set
-   * @param values the sequence of values the parameter is to be set to
-   * @param type the SQL type of the values to send to the database
-   * @return this Operation
-   * @throws IllegalArgumentException if the length of values is not the same as
-   * the length of the previously set parameter sequences or if the same id was
-   * passed in a previous call.
-   * @throws IllegalStateException if the {@link Operation} has been submitted
-   */
-  public ArrayCountOperation<T> set(String id, List<?> values, SqlType type);
-
-  /**
-   * Set a sequence of parameter values. Use a default SQL type determined by
-   * the type of the value argument. The value is captured and should not be
-   * modified before the {@link Operation} is completed.
-   *
-   * The Operation is completed exceptionally with ClassCastException if any of
-   * the values cannot be converted to the specified SQL type.
-   *
-   * @param id the identifier of the parameter marker to be set
-   * @param values the value the parameter is to be set to
-   * @return this {@link Operation}
-   * @throws IllegalArgumentException if the length of value is not the same as
-   * the length of the previously set parameter sequences or if the same id was
-   * passed in a previous call.
-   * @throws IllegalStateException if the {@link Operation} has been submitted
-   */
-  public ArrayCountOperation<T> set(String id, List<?> values);
-
-  /**
-   * Set a sequence of parameter values. The first parameter is captured and
-   * should not be modified before the {@link Operation} is completed.
-   *
-   * The Operation is completed exceptionally with ClassCastException if any of
-   * the values cannot be converted to the specified SQL type.
-   *
-   * @param <S> the Java type of the individual parameter values
-   * @param id the identifier of the parameter marker to be set
-   * @param values the value the parameter is to be set to
-   * @param type the SQL type of the value to send to the database
-   * @return this Operation
-   * @throws IllegalArgumentException if the length of value is not the same as
-   * the length of the previously set parameter sequences or if the same id was
-   * passed in a previous call.
-   * @throws IllegalStateException if the {@link Operation} has been submitted
-   */
-  public <S> ArrayCountOperation<T> set(String id, S[] values, SqlType type);
-
-  /**
-   * Set a sequence of parameter values. Use a default SQL type determined by
-   * the type of the value argument. The parameter is captured and should not be
-   * modified before the {@link Operation} is completed.
-   *
-   * The Operation is completed exceptionally with ClassCastException if any of
-   * the values cannot be converted to the specified SQL type.
-   *
-   * @param <S> the Java type of the individual parameter values
-   * @param id the identifier of the parameter marker to be set
-   * @param values the value the parameter is to be set to
-   * @return this Operation
-   * @throws IllegalArgumentException if the length of value is not the same as
-   * the length of the previously set parameter sequences or if the same id was
-   * passed in a previous call.
-   * @throws IllegalStateException if the {@link Operation} has been submitted
-   */
-  public <S> ArrayCountOperation<T> set(String id, S[] values);
-
-  /**
-   * Provide a source for a sequence of parameter values.
-   *
-   * This Operation is not executed until source is completed normally. If
-   * source completes exceptionally this Operation completes exceptionally with
-   * an IllegealArgumentException with the source's exception as the cause.
-   *
-   * The Operation is completed exceptionally with ClassCastException if any of
-   * the values of the source cannot be converted to the specified SQL type.
-   *
-   * If the length of the value of source is not the same as the length of all
-   * other parameter sequences this Operation is completed exceptionally with
-   * IllegalArgumentException.
-   *
-   * @param id the identifier of the parameter marker to be set
-   * @param source supplies the values the parameter is to be set to
-   * @param type the SQL type of the value to send to the database
-   * @return this Operation
-   * @throws IllegalArgumentException if the same id was passed in a previous
-   * call.
-   * @throws IllegalStateException if the {@link Operation} has been submitted
-   */
-  public ArrayCountOperation<T> set(String id, CompletionStage<?> source, SqlType type);
-
-  /**
-   * Provide a source for a sequence of parameter values. Use a default SQL type
-   * determined by the element type of the value of the source.
-   *
-   * This Operation is not executed until source is completed normally. If
-   * source completes exceptionally this Operation completes exceptionally with
-   * an IllegealArgumentException with the source's exception as the cause.
-   *
-   * The Operation is completed exceptionally with ClassCastException if any of
-   * the values of the source cannot be converted to the specified SQL type.
-   *
-   * If the length of the value of source is not the same as the length of all
-   * other parameter sequences this Operation is completed exceptionally with
-   * IllegalArgumentException.
-   *
-   * @param id the identifier of the parameter marker to be set
-   * @param source supplies the values the parameter is to be set to
-   * @return this {@link Operation}
-   * @throws IllegalArgumentException if the same id was passed in a previous
-   * call.
-   * @throws IllegalStateException if the {@link Operation} has been submitted
-   */
-  public ArrayCountOperation<T> set(String id, CompletionStage<?> source);
-
-  /**
-   * Provides a {@link Collector} to reduce the sequence of Counts.The result of
-   * the {@link Operation} is the result of calling finisher on the final
-   * accumulated result. If the {@link Collector} is
-   * {@link Collector.Characteristics#UNORDERED} counts may be accumulated out of
-   * order. If the {@link Collector} is
-   * {@link Collector.Characteristics#CONCURRENT} then the sequence of counts may be
-   * split into subsequences that are reduced separately and then combined.
-   *
-   * @param <A> the type of the accumulator
-   * @param <S> the type of the final result
-   * @param c the Collector. Not null. 
-   * @return This ArrayCountOperation
-   * @throws IllegalStateException if this method had been called previously or
-   * this Operation has been submitted.
-  */
-  public <A, S extends T> ArrayCountOperation<T> collect(Collector<? super Result.Count, A, S> c);
-
-  @Override
-  public ArrayCountOperation<T> onError(Consumer<Throwable> handler);
-
-  @Override
-  public ArrayCountOperation<T> timeout(Duration minTime);
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ArrayRowCountOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+import java.util.function.Consumer;
+import java.util.stream.Collector;
+
+/**
+ * A database operation that returns a count that is executed multiple times
+ * with multiple sets of parameter values in one database operation. The
+ * parameters are submitted to the database in the same order as in the
+ * sequences passed to the set methods. The count results are passed to the
+ * collector in the same order they are produced by the database. The
+ * value of the Operation is the final result produced by the collector.
+ *
+ * @param <T> the type of the result of collecting the counts
+ */
+public interface ArrayRowCountOperation<T> extends Operation<T> {
+
+  /**
+   * Set a sequence of parameter values. The value is captured and should not be
+   * modified before the {@link Operation} is completed.
+   *
+   * The Operation is completed exceptionally with ClassCastException if any of
+   * the values cannot be converted to the specified SQL type.
+   *
+   * @param id the identifier of the parameter marker to be set
+   * @param values the sequence of values the parameter is to be set to
+   * @param type the SQL type of the values to send to the database
+   * @return this Operation
+   * @throws IllegalArgumentException if the length of values is not the same as
+   * the length of the previously set parameter sequences or if the same id was
+   * passed in a previous call.
+   * @throws IllegalStateException if the {@link Operation} has been submitted
+   */
+  public ArrayRowCountOperation<T> set(String id, List<?> values, SqlType type);
+
+  /**
+   * Set a sequence of parameter values. Use a default SQL type determined by
+   * the type of the value argument. The value is captured and should not be
+   * modified before the {@link Operation} is completed.
+   *
+   * The Operation is completed exceptionally with ClassCastException if any of
+   * the values cannot be converted to the specified SQL type.
+   *
+   * @param id the identifier of the parameter marker to be set
+   * @param values the value the parameter is to be set to
+   * @return this {@link Operation}
+   * @throws IllegalArgumentException if the length of value is not the same as
+   * the length of the previously set parameter sequences or if the same id was
+   * passed in a previous call.
+   * @throws IllegalStateException if the {@link Operation} has been submitted
+   */
+  public ArrayRowCountOperation<T> set(String id, List<?> values);
+
+  /**
+   * Set a sequence of parameter values. The first parameter is captured and
+   * should not be modified before the {@link Operation} is completed.
+   *
+   * The Operation is completed exceptionally with ClassCastException if any of
+   * the values cannot be converted to the specified SQL type.
+   *
+   * @param <S> the Java type of the individual parameter values
+   * @param id the identifier of the parameter marker to be set
+   * @param values the value the parameter is to be set to
+   * @param type the SQL type of the value to send to the database
+   * @return this Operation
+   * @throws IllegalArgumentException if the length of value is not the same as
+   * the length of the previously set parameter sequences or if the same id was
+   * passed in a previous call.
+   * @throws IllegalStateException if the {@link Operation} has been submitted
+   */
+  public <S> ArrayRowCountOperation<T> set(String id, S[] values, SqlType type);
+
+  /**
+   * Set a sequence of parameter values. Use a default SQL type determined by
+   * the type of the value argument. The parameter is captured and should not be
+   * modified before the {@link Operation} is completed.
+   *
+   * The Operation is completed exceptionally with ClassCastException if any of
+   * the values cannot be converted to the specified SQL type.
+   *
+   * @param <S> the Java type of the individual parameter values
+   * @param id the identifier of the parameter marker to be set
+   * @param values the value the parameter is to be set to
+   * @return this Operation
+   * @throws IllegalArgumentException if the length of value is not the same as
+   * the length of the previously set parameter sequences or if the same id was
+   * passed in a previous call.
+   * @throws IllegalStateException if the {@link Operation} has been submitted
+   */
+  public <S> ArrayRowCountOperation<T> set(String id, S[] values);
+
+  /**
+   * Provide a source for a sequence of parameter values.
+   *
+   * This Operation is not executed until source is completed normally. If
+   * source completes exceptionally this Operation completes exceptionally with
+   * an IllegealArgumentException with the source's exception as the cause.
+   *
+   * The Operation is completed exceptionally with ClassCastException if any of
+   * the values of the source cannot be converted to the specified SQL type.
+   *
+   * If the length of the value of source is not the same as the length of all
+   * other parameter sequences this Operation is completed exceptionally with
+   * IllegalArgumentException.
+   *
+   * @param id the identifier of the parameter marker to be set
+   * @param source supplies the values the parameter is to be set to
+   * @param type the SQL type of the value to send to the database
+   * @return this Operation
+   * @throws IllegalArgumentException if the same id was passed in a previous
+   * call.
+   * @throws IllegalStateException if the {@link Operation} has been submitted
+   */
+  public ArrayRowCountOperation<T> set(String id, CompletionStage<?> source, SqlType type);
+
+  /**
+   * Provide a source for a sequence of parameter values. Use a default SQL type
+   * determined by the element type of the value of the source.
+   *
+   * This Operation is not executed until source is completed normally. If
+   * source completes exceptionally this Operation completes exceptionally with
+   * an IllegealArgumentException with the source's exception as the cause.
+   *
+   * The Operation is completed exceptionally with ClassCastException if any of
+   * the values of the source cannot be converted to the specified SQL type.
+   *
+   * If the length of the value of source is not the same as the length of all
+   * other parameter sequences this Operation is completed exceptionally with
+   * IllegalArgumentException.
+   *
+   * @param id the identifier of the parameter marker to be set
+   * @param source supplies the values the parameter is to be set to
+   * @return this {@link Operation}
+   * @throws IllegalArgumentException if the same id was passed in a previous
+   * call.
+   * @throws IllegalStateException if the {@link Operation} has been submitted
+   */
+  public ArrayRowCountOperation<T> set(String id, CompletionStage<?> source);
+
+  /**
+   * Provides a {@link Collector} to reduce the sequence of Counts.The result of
+   * the {@link Operation} is the result of calling finisher on the final
+   * accumulated result. If the {@link Collector} is
+   * {@link Collector.Characteristics#UNORDERED} counts may be accumulated out of
+   * order. If the {@link Collector} is
+   * {@link Collector.Characteristics#CONCURRENT} then the sequence of counts may be
+   * split into subsequences that are reduced separately and then combined.
+   *
+   * @param <A> the type of the accumulator
+   * @param <S> the type of the final result
+   * @param c the Collector. Not null. 
+   * @return This ArrayRowCountOperation
+   * @throws IllegalStateException if this method had been called previously or
+   * this Operation has been submitted.
+  */
+  public <A, S extends T> ArrayRowCountOperation<T> collect(Collector<? super Result.RowCount, A, S> c);
+
+  @Override
+  public ArrayRowCountOperation<T> onError(Consumer<Throwable> handler);
+
+  @Override
+  public ArrayRowCountOperation<T> timeout(Duration minTime);
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Connection.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Connection.java	Wed Jun 20 15:38:40 2018 -0400
@@ -259,12 +259,15 @@
      * Return a {@link Connection} with the attributes specified. Note that the
      * {@link Connection} may not be connected to a server. Call one of the
      * {@link connect} convenience methods to connect the {@link Connection} to
-     * a server. The lifecycle of the new {@link Connection} is {@link Lifecycle#NEW}.
+     * a server. The lifecycle of the new {@link Connection} is
+     * {@link Lifecycle#NEW}.
      *
      * @return a {@link Connection}
      * @throws IllegalStateException if this method has already been called or
      * if the implementation cannot create a Connection with the specified
      * {@link ConnectionProperty}s.
+     * @throws IllegalStateException if the {@link DataSource} that created this
+     * {@link Builder} is closed
      */
     public Connection build();
   }
@@ -471,13 +474,14 @@
   
   /**
    * Create an endTransaction {@link Operation}, set it to rollback only,
-   * and submit it. Convenience method.
+   * and submit it. The endTransaction is never skipped. Convenience method.
    *
    * @return this {@link OperationGroup}
    */
   public default CompletionStage<TransactionOutcome> rollback() {
     Transaction t = transaction();
     t.setRollbackOnly();
+    catchErrors();
     return this.endTransactionOperation(t).submit().getCompletionStage();
   }
 
@@ -547,6 +551,29 @@
   public ShardingKey.Builder shardingKeyBuilder();
 
   /**
+   * Provide a method that this {@link Connection} will call to control the rate
+   * of {@link Operation} submission. This {@link Connection} will call
+   * {@code request} with a positive argument when the {@link Connection} is
+   * able to accept more {@link Operation} submissions. The difference between
+   * the sum of all arguments passed to {@code request} and the number of
+   * {@link Operation}s submitted after this method is called is the
+   * <i>demand</i>. The demand must always be non-negative. If an
+   * {@link Operation} is submitted that would make the demand negative the call
+   * to {@link Operation#submit} throws {@link IllegalStateException}. Prior to
+   * a call to {@code requestHook}, the demand is defined to be infinite.
+   * After a call to {@code requestHook}, the demand is defined to be
+   * zero and is subsequently computed as described previously.
+   * {@link Operation}s submitted prior to the call to {@code requestHook} do
+   * not affect the demand.
+   *
+   * @param request accepts calls to increase the demand. Not null.
+   * @return this {@link Connection}
+   * @throws IllegalStateException if this method has been called previously or
+   * this {@link Connection} is not active.
+   */
+  public Connection requestHook(Consumer<Long> request);
+
+  /**
    * Make this {@link Connection} ready for use. A newly created
    * {@link Connection} is active. Calling this method on a {@link Connection}
    * that is active is a no-op. If the lifecycle is {@link Lifecycle#INACTIVE}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSource.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSource.java	Wed Jun 20 15:38:40 2018 -0400
@@ -30,7 +30,7 @@
 import java.util.function.Consumer;
 
 /**
- * Uses the builder pattern to get a {@link Connection}. A {@link getConnection}
+ * Uses the builder pattern to get a {@link Connection}. A {@link DataSource#getConnection}
  * method is provided as a convenience.
  * 
  * Implementations must be thread safe.
@@ -42,6 +42,8 @@
    * Instances of this type are used to build {@link DataSource}s. This type is 
    * immutable once configured. No property can be set more than once. No 
    * property can be set after {@link build} is called. 
+   * 
+   * ISSUE: Probably need property(DataSourceProperty prop, Object value).
    */
   public interface Builder {
 
@@ -135,6 +137,34 @@
     }
 
     /**
+     * Provide a method that the built {@link DataSource} will call to control the
+     * rate of {@link DataSource#connectOperation} submissions. The built
+     * {@link DataSource} will call {@code request} with a positive argument
+     * when the {@link DataSource} is able to accept more
+     * {@link DataSource#connectOperation} submissions. The difference between
+     * the sum of all arguments passed to {@code request} and the number of
+     * calls to {@link DataSource#builder} is the
+     * <i>demand</i>. The demand must always be non-negative. If a call is made to
+     * {@link DataSource#builder} that would make the demand negative that call 
+     * throws {@link IllegalStateException}. If {@code requestHook} is not called,
+     * the demand is defined to be infinite.
+     * 
+     * <p>
+     * An implementation may choose to delay detection of insufficient demand. 
+     * Instead of checking when {@link DataSource#builder} is called an 
+     * implementation may choose to check at some later point in Connection 
+     * creation such as {@link Connection.Builder.build} or 
+     * {@code Connection#connectOperation().submit()} or even later. In any case
+     * an implementation must throw IllegalStateException before allocating
+     * or waiting to allocate scarce resources if the demand is negative.</p>
+     *
+     * @param request accepts calls to increase the demand. Not null.
+     * @return this {@link Builder}
+     * @throws IllegalStateException if this method has been called previously
+     */
+    public Builder requestHook(Consumer<Long> request);
+
+    /**
      * Return a DataSource configured as specified. 
      *
      * @return a configured {@link DataSource}. Not {@code null}.
@@ -151,6 +181,7 @@
    * the returned builder.
    *
    * @return a new {@link Connection} builder. Not {@code null}.
+   * @throws IllegalStateException if this {@link DataSource} is closed
    */
   public Connection.Builder builder();
 
@@ -159,6 +190,7 @@
    * method for use with try with resources.
    *
    * @return a {@link Connection}
+   * @throws IllegalStateException if this {@link DataSource} is closed
    */
   public default Connection getConnection() {
     return builder().build().connect();
@@ -171,6 +203,7 @@
    *
    * @param handler for errors in the connect {@link Operation}
    * @return a {@link Connection}
+   * @throws IllegalStateException if this {@link DataSource} is closed
    */
   public default Connection getConnection(Consumer<Throwable> handler) {
     return builder().build().connect(handler);
@@ -188,6 +221,7 @@
    * @return SQL in the format supported by this {@link DataSource}. Not {@code null}.
    * @throws IllegalArgumentException if the {@code format} is not supported or
    * if the {@link DataSource} cannot translate the SQL
+   * @throws IllegalStateException if this {@link DataSource} is closed
    */
   public default String translateSql(String format, String source) throws SqlException {
     throw new IllegalArgumentException("Unsupported format: \"" + format + "\"");
@@ -199,6 +233,7 @@
    * ISSUE: Just an idea
    * 
    * @return an array of Strings each of which identifies a supported format
+   * @throws IllegalStateException if this {@link DataSource} is closed
    */
   public default List<String> supportedTranslateSqlFormats() {
     return new LinkedList<>();
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSourceFactory.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSourceFactory.java	Wed Jun 20 15:38:40 2018 -0400
@@ -26,7 +26,6 @@
 
 import java.util.ServiceLoader;
 import java.util.ServiceLoader.Provider;
-import java.util.function.Function;
 
 /**
  * This interface supports injecting a {@link DataSourceFactory}. The SPI
@@ -42,13 +41,14 @@
    * Uses SPI to find a {@link DataSourceFactory} with the requested name or
    * {@code null} if one is not found.
    *
+   * @param <T>
    * @param name the name of the class that implements the factory
    * @return a {@link DataSourceFactory} for {@code name} or {@code null} if one
    * is not found
    */
-  public static DataSourceFactory forName(String name) {
+  public static <T extends DataSourceFactory> T newFactory(String name) {
     if (name == null) throw new IllegalArgumentException("DataSourceFactory name is null");
-    return ServiceLoader
+    return (T)ServiceLoader
             .load(DataSourceFactory.class)
             .stream()
             .filter(p -> p.type().getName().equals(name))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Examples.java	Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,371 @@
+package jdk.incubator.sql2;
+
+/*
+ * Copyright (c)  2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Flow;
+import java.util.concurrent.Semaphore;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+/**
+ * Simple example code using various aspects of ADBA. These do not necessarily
+ * demonstrate the best way to use each feature, just one way.
+ */
+public class Examples {
+  
+  // DataSourceFactory
+
+  public DataSource getDataSource(String url, String user, String pass) {
+    return DataSourceFactory.newFactory("oracle.database.adba")
+            .builder()
+            .url("//host.oracle.com:5521/example")
+            .username("scott")
+            .password("tiger")
+            .build();
+  }
+  
+  // RowCountOperation
+  
+  public void insertItem(DataSource ds, Item item) {
+    try (Connection conn = ds.getConnection()) {
+      conn.rowCountOperation("insert into tab values (:id, :name, :answer)")
+              .set("id", item.id(), AdbaType.NUMERIC)
+              .set("name", item.name(), AdbaType.VARCHAR)
+              .set("answer", item.answer(), AdbaType.NUMERIC)
+              .submit();
+    }
+  }
+  
+  // RowOperation
+  
+  public void idsForAnswer(DataSource ds, List<Integer> result, int correctAnswer) {
+    try (Connection conn = ds.getConnection()) {
+      conn.<List<Integer>>rowOperation("select id, name, answer from tab where answer = :target")
+              .set("target", correctAnswer, AdbaType.NUMERIC)
+              .collect(() -> result, 
+                       (list, row) -> list.add(row.at("id").get(Integer.class)) )
+              .submit();
+    }
+  }
+  
+  // RowOperation
+  
+  public CompletionStage<List<Item>> itemsForAnswer(DataSource ds, int answer) {
+    try (Connection conn = ds.getConnection()) {
+      return conn.<List<Item>>rowOperation("select id, name, answer from tab where answer = :target")
+              .set("target", 42, AdbaType.NUMERIC)
+              .collect(Collectors.mapping( 
+                       row -> new Item(row.at("id").get(Integer.class),
+                                       row.at("name").get(String.class),
+                                       row.at("answer").get(Integer.class) ),
+                       Collectors.toList() ))
+              .submit()
+              .getCompletionStage();
+    }
+  }
+  
+  // Independent OperationGroup
+
+  public void insertItemsIndependent(DataSource ds, List<Item> list) {
+    String sql = "insert into tab values (:id, :name, :answer)";
+    try (Connection conn = ds.getConnection()) {
+      OperationGroup group = conn.operationGroup()
+              .independent();
+      for (Item elem : list) {
+        group.rowCountOperation(sql)
+                .set("id", elem.id)
+                .set("name", elem.name)
+                .set("answer", elem.answer)
+                .submit()
+                .getCompletionStage()
+                .exceptionally( t -> {
+                  System.out.println(elem.id);
+                  return null;
+                });
+      }
+      group.submit();
+    }
+  }
+  
+  // Held OperationGroup
+  
+  public void insertItemsHold(DataSource ds, List<Item> list) {
+    String sql = "insert into tabone values (:id, :name, :answer)";
+    try (Connection conn = ds.getConnection()) {
+      OperationGroup group = conn.operationGroup()
+              .independent();
+      group.submitHoldingForMoreMembers();
+      for (Item elem : list) {
+        group.rowCountOperation(sql)
+                .set("elem_", elem)
+                .submit()
+                .getCompletionStage()
+                .exceptionally( t -> {
+                  System.out.println(elem.id);
+                  return null;
+                });
+      }
+      group.releaseProhibitingMoreMembers();
+    }
+  }
+  
+  // Parallel, Independent OperationGroup
+  
+  public void updateListParallel(List<Item> list, DataSource ds) {
+    String query = "select id from tab where answer = :answer";
+    String update = "update tab set name = :name where id = :id";
+    try (Connection conn = ds.getConnection()) {
+      OperationGroup<Object, Object> group = conn.operationGroup()
+              .independent()
+              .parallel();
+      group.submitHoldingForMoreMembers();
+      for (Item elem : list) {
+        CompletionStage<Integer> idPromise = group.<List<Integer>>rowOperation(query)
+                .set("answer", elem.answer, AdbaType.NUMERIC)
+                .collect( Collector.of(
+                        () -> new ArrayList<>(),
+                        (l, row) -> l.add( row.at("id").get(Integer.class) ),
+                        (l, r) -> l ))
+                .submit()
+                .getCompletionStage()
+                .thenApply( l -> l.get(0) );
+        group.rowCountOperation(update)
+                .set("id", idPromise)
+                .set("name", "the ultimate question")
+                .submit()
+                .getCompletionStage()
+                .exceptionally( t -> {
+                  System.out.println(elem.id);
+                  return null;
+                });
+      }
+      group.releaseProhibitingMoreMembers();
+    }
+  }
+  
+  // Transaction
+  
+  public void transaction(DataSource ds) {
+    try (Connection conn = ds.getConnection(t -> System.out.println("ERROR: " + t.toString()))) {
+      Transaction trans = conn.transaction();
+      CompletionStage<Integer> idPromise = conn.<Integer>rowOperation("select empno, ename from emp where ename = :1 for update")
+              .set("1", "CLARK", AdbaType.VARCHAR)
+              .collect(Collectors.collectingAndThen(
+                                        Collectors.mapping(r -> r.at("empno").get(Integer.class), 
+                                                           Collectors.toList()), 
+                                        l -> l.get(0)))
+              .onError( t -> trans.setRollbackOnly() )
+              .submit()
+              .getCompletionStage();
+      conn.<Long>rowCountOperation("update emp set deptno = :1 where empno = :2")
+              .set("1", 50, AdbaType.INTEGER)
+              .set("2", idPromise, AdbaType.INTEGER)
+              .apply(c -> { 
+                if (c.getCount() != 1L) {
+                  trans.setRollbackOnly();
+                  throw new RuntimeException("updated wrong number of rows");
+                }
+                return c.getCount();
+              })
+              .onError(t -> trans.setRollbackOnly() )
+              .submit();
+          //    .getCompletionStage()
+          //    .exceptionally( t -> { trans.setRollbackOnly(); return null; } ) // incorrect
+      conn.catchErrors();
+      conn.commitMaybeRollback(trans);
+    }    
+  }
+  
+  // RowPublisherOperation
+  
+  public CompletionStage<List<String>> rowSubscriber(DataSource ds) {
+    
+    String sql = "select empno, ename from emp";
+    CompletableFuture<List<String>> result = new CompletableFuture<>();
+
+    Flow.Subscriber<Result.RowColumn> subscriber = new Flow.Subscriber<>() {
+
+      Flow.Subscription subscription;
+      List<String> names = new ArrayList<>();
+      int demand = 0;
+
+      @Override
+      public void onSubscribe(Flow.Subscription subscription) {
+        this.subscription = subscription;
+        this.subscription.request(10);
+        demand += 10;
+      }
+
+      @Override
+      public void onNext(Result.RowColumn column) {
+        names.add(column.at("ename").get(String.class));
+        if (--demand < 1) {
+          subscription.request(10);
+          demand += 10;
+        }
+      }
+
+      @Override
+      public void onError(Throwable throwable) {
+        result.completeExceptionally(throwable);
+      }
+
+      @Override
+      public void onComplete() {
+        result.complete(names);
+      }
+
+    };
+    
+    try (Connection conn = ds.getConnection()) {
+      return conn.<List<String>>rowPublisherOperation(sql)
+              .subscribe(subscriber, result)
+              .submit()
+              .getCompletionStage();
+    }
+  }
+  
+  // Control Operation Submission Rate
+    
+  public CompletionStage<Long> insertRecords(DataSource ds, DataInputStream in) {
+    String insert = "insert into tab values (@record)";
+    try (Connection conn = ds.getConnection()) {
+      OperationGroup<Long, Long> group = conn.<Long, Long>operationGroup()
+              .independent()
+              .collect(Collectors.summingLong(c -> c));
+      group.submitHoldingForMoreMembers();
+      Semaphore demand = new Semaphore(0);
+      conn.requestHook( n -> demand.release(n.intValue()) );
+      while (in.available() > 0) {
+        demand.acquire(1); // user thread blocked by Semaphore, not by ADBA
+        group.<Long>rowCountOperation(insert)
+                    .set("record", in.readUTF(), AdbaType.VARCHAR)
+                    .apply(c -> c.getCount())
+                    .submit();
+      }
+      return group.releaseProhibitingMoreMembers()
+                  .getCompletionStage();
+    }
+    catch (IOException | InterruptedException ex) { 
+      throw new SqlException(ex);
+    }
+  }  
+  
+  // ArrayRowCountOperation
+  
+  public CompletionStage<Long> arrayInsert(DataSource ds, 
+                                           List<Integer> ids, 
+                                           List<String> names, 
+                                           List<Integer> answers) {
+    String sql = "insert into tab values (?, ?, ?)";
+    try (Connection conn = ds.getConnection()) {
+      return conn.<Long>arrayRowCountOperation(sql)
+          .collect(Collectors.summingLong( c -> c.getCount() ))
+          .set("1",ids, AdbaType.INTEGER)
+          .set("2", names, AdbaType.VARCHAR)
+          .set("3", answers, AdbaType.INTEGER)
+          .submit()
+          .getCompletionStage();
+    }
+  }
+  
+  // ArrayRowCountOperation -- transposed
+  
+  public CompletionStage<Long> transposedArrayInsert(DataSource ds, List<Item> items) {
+    String sql = "insert into tab values (?, ?, ?)";
+    try (Connection conn = ds.getConnection()) {
+      return conn.<Long>arrayRowCountOperation(sql)
+          .collect(Collectors.summingLong( c -> c.getCount() ))
+          .set("1", items.stream().map(Item::id).collect(Collectors.toList()), AdbaType.INTEGER)
+          .set("2", items.stream().map(Item::name).collect(Collectors.toList()), AdbaType.VARCHAR)
+          .set("3", items.stream().map(Item::answer).collect(Collectors.toList()), AdbaType.INTEGER)
+          .submit()
+          .getCompletionStage();
+    }
+  }
+  
+  // OutOperation
+  
+  public CompletionStage<Item> getItem(DataSource ds, int id) {
+    String sql = "call item_for_id(:id, :name, :answer)";
+    try (Connection conn = ds.getConnection()) {
+      return conn.<Item>outOperation(sql)
+              .set("id", id, AdbaType.INTEGER)
+              .outParameter("name", AdbaType.VARCHAR)
+              .outParameter("answer", AdbaType.INTEGER)
+              .apply( out -> new Item(id, 
+                                      out.at("name").get(String.class), 
+                                      out.at("answer").get(Integer.class)) )
+              .submit()
+              .getCompletionStage();
+    }
+  }
+  
+  // MultiOperation
+  
+  // LocalOperation
+  
+  // ConnectionProperty
+  
+  // Sharding
+  
+  // TransactionOutcome
+  
+  // Column navigation
+  
+  // Error handling
+  
+  static public class Item {
+    public int id;
+    public String name;
+    public int answer;
+    
+    public Item(int i, String n, int a) {
+      id =i;
+      name = n;
+      answer = a;
+    }
+    
+    public int id() {
+      return id;
+    }
+    
+    public String name() {
+      return name;
+    }
+    
+    public int answer() {
+      return answer;
+    }
+  }
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/MultiOperation.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/MultiOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -33,14 +33,15 @@
 /**
  * A multi-operation is an {@link Operation} that returns one or more results in
  * addition to the out result defined by the {@link Operation}. Each result is
- * processed by an Operation. The Operations can be created by calling rowOperation,
- * rowProcessorOperation, or countOperation if the kind of results is known. These
- * results are processed in the order the Operations are submitted. Any results
- * not processed by an explicit Operation is processed by calling the appropriate
- * handler specified by onRows or onCount. If any result is an error that error
- * is processed by calling the handler specified by onError. If the appropriate
- * handler is not specified that result is ignored, including errors.
- * 
+ * processed by an Operation. The Operations can be created by calling
+ * rowOperation, rowProcessorOperation, or countOperation if the kind of results
+ * is known. These results are processed in the order the Operations are
+ * submitted. Any results not processed by an explicit Operation is processed by
+ * calling the appropriate handler specified by onRows or onCount. If any result
+ * is an error that error is processed by calling the handler specified by
+ * onError. If the appropriate handler is not specified that result is ignored,
+ * including errors.
+ *
  * ISSUE: Should this have a collector?
  *
  * @param <T> The type of the result of this {@link Operation}
@@ -51,86 +52,90 @@
    * Returns a {@link RowOperation} to process a row sequence result. The
    * {@link Operation}s are executed in the order they are submitted. If a
    * result is of the wrong type for the next submitted {@link Operation} the
-   * {@link MultiOperation} is completed with
-   * {@link IllegalStateException}.
+   * {@link MultiOperation} is completed with {@link IllegalStateException}.
    *
    * @return a {@link RowOperation} that is part of this {@link MultiOperation}
    */
   public RowOperation<T> rowOperation();
 
   /**
-   * Returns a {@link RowProcessorOperation} to process a row sequence result. The
-   * {@link Operation}s are executed in the order they are submitted. If a
+   * Returns a {@link RowPublisherOperation} to process a row sequence result.
+   * The {@link Operation}s are executed in the order they are submitted. If a
    * result is of the wrong type for the next submitted {@link Operation} the
-   * {@link MultiOperation} is completed with
-   * {@link IllegalStateException}.
+   * {@link MultiOperation} is completed with {@link IllegalStateException}.
    *
-   * @return a {@link RowProcessorOperation} that is part of this {@link MultiOperation}
+   * @return a {@link RowPublisherOperation} that is part of this
+   * {@link MultiOperation}
    */
-  public RowProcessorOperation<T> rowProcessorOperation();
+  public RowPublisherOperation<T> rowProcessorOperation();
 
   /**
-   * Returns a {@link CountOperation} to process a count result. The {@link Operation}s
-   * are executed in the order they are submitted. If a result is of the wrong
-   * type for the next submitted Operation the {@link MultiOperation} is completed
-   * with {@link IllegalStateException}.
+   * Returns a {@link RowCountOperation} to process a count result. The
+   * {@link Operation}s are executed in the order they are submitted. If a
+   * result is of the wrong type for the next submitted Operation the
+   * {@link MultiOperation} is completed with {@link IllegalStateException}.
    *
-   * @return a {@link CountOperation} that is part of this {@link MultiOperation}
+   * @return a {@link RowCountOperation} that is part of this
+   * {@link MultiOperation}
    */
-  public CountOperation<T> countOperation();
+  public RowCountOperation<T> rowCountOperation();
 
   /**
-   * Provides a handler for trailing count results. The provided handler is called for
-   * each count result not processed by CountOperation. When called the first argument is the number of results
-   * that preceeded the current result. The second argument is a
-   * {@link CountOperation} that will process the current result. This
-   * {@link CountOperation} has not been configured in any way nor has it been
-   * submitted. The handler configures the {@link CountOperation} and submits
-   * it. The count result is processed when the {@link CountOperation} is
-   * submitted. If the {@link CountOperation} is not submitted when the handler
-   * returns the count result is ignored.
-   * 
+   * Provides a handler for trailing count results. The provided handler is
+   * called for each count result not processed by RowCountOperation. When
+   * called the first argument is the number of results that preceeded the
+   * current result. The second argument is a {@link RowCountOperation} that
+   * will process the current result. This {@link RowCountOperation} has not
+   * been configured in any way nor has it been submitted. The handler
+   * configures the {@link RowCountOperation} and submits it. The count result
+   * is processed when the {@link RowCountOperation} is submitted. If the
+   * {@link RowCountOperation} is not submitted when the handler returns the
+   * count result is ignored.
+   *
    * If this method is not called any trailing count results are ignored.
    *
    * @param handler not null
    * @return this MultiOperation
    * @throws IllegalStateException if this method was called previously
    */
-  public MultiOperation<T> onCount(BiConsumer<Integer, CountOperation<T>> handler);
+  public MultiOperation<T> onCount(BiConsumer<Integer, RowCountOperation<T>> handler);
 
   /**
-   * Provides a handler for trailing row sequence results. The provided handler is called
-   * for each row sequence result not processed by a RowOperation. When called the first argument is the number
-   * of results that preceeded the current result. The second argument is a
-   * {@link RowOperation} that will process the current result. This
-   * {@link RowOperation} has not been configured in any way nor has it been
-   * submitted. The handler configures the {@link RowOperation} and submits it.
-   * The row sequence result is processed when the {@link RowOperation} is
-   * submitted. If the {@link RowOperation} is not submitted when the handler
-   * returns, the row sequence result is ignored.
-   * 
+   * Provides a handler for trailing row sequence results. The provided handler
+   * is called for each row sequence result not processed by a RowOperation.
+   * When called the first argument is the number of results that preceeded the
+   * current result. The second argument is a {@link RowOperation} that will
+   * process the current result. This {@link RowOperation} has not been
+   * configured in any way nor has it been submitted. The handler configures the
+   * {@link RowOperation} and submits it. The row sequence result is processed
+   * when the {@link RowOperation} is submitted. If the {@link RowOperation} is
+   * not submitted when the handler returns, the row sequence result is ignored.
+   *
    * If this method is not called any trailing row sequence results are ignored.
-   * 
-   * ISSUE: Should there be a version of this method that provides 
-   * RowProcessorOperations? If so only one of that method or this one can be called.
+   *
+   * ISSUE: Should there be a version of this method that provides
+   * RowProcessorOperations? If so only one of that method or this one can be
+   * called.
    *
    * @param handler
    * @return This MultiOperation
    * @throws IllegalStateException if this method was called previously
    */
   public MultiOperation<T> onRows(BiConsumer<Integer, RowOperation<T>> handler);
-  
+
   /**
-   * Provides an error handler for this {@link Operation}. The provided handler 
-   * is called for each error that occurs. When called the first argument is the 
+   * Provides an error handler for this {@link Operation}. The provided handler
+   * is called for each error that occurs. When called the first argument is the
    * number of results, including errors, that preceeded the current error. The
    * second argument is a {@link Throwable} corresponding to the error. When the
-   * handler returns processing of the MultiOperation results continues. 
-   * Only one onError method may be called.
-   * 
+   * handler returns processing of the MultiOperation results continues. Only
+   * one onError method may be called.
+   *
    * @param handler a BiConsumer that handles an error
    * @return this MultiOperation
-   * @throws IllegalStateException if this method was called previously
+   * @throws IllegalStateException if this method or 
+   * {@link MultiOperation#onError(java.util.function.Consumer)} was called 
+   * previously
    */
   public MultiOperation<T> onError(BiConsumer<Integer, Throwable> handler);
   // Covariant overrides
@@ -139,15 +144,15 @@
    * This handler is called if the execution fails completely. If the execution
    * returns any individual results, even if any or all of those results are
    * errors, this handler is not called.
-   * 
+   *
    * @param handler
-   * @return 
+   * @return
    */
   @Override
   public MultiOperation<T> onError(Consumer<Throwable> handler);
-  
+
   @Override
-  public MultiOperation<T> apply(Function<Result.OutParameterMap, ? extends T> processor);
+  public MultiOperation<T> apply(Function<Result.OutColumn, ? extends T> processor);
 
   @Override
   public MultiOperation<T> outParameter(String id, SqlType type);
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java	Wed Jun 20 15:38:40 2018 -0400
@@ -26,7 +26,6 @@
 
 import java.time.Duration;
 import java.util.concurrent.CompletionStage;
-import java.util.concurrent.Flow;
 import java.util.function.Consumer;
 import java.util.logging.Logger;
 import java.util.stream.Collector;
@@ -195,7 +194,7 @@
    *
    * ISSUE: Need a better name.
    *
-   * @return a Submission
+   * @return a Submission for this OperationGroup
    * @throws IllegalStateException if this {@link OperationGroup} has been
    * submitted
    */
@@ -209,19 +208,16 @@
    * queue this {@link OperationGroup} will be completed and removed from the
    * queue.
    *
-   * Calling this method when this {@link OperationGroup} is not held is a
-   * no-op.
-   *
    * Note: There is no covariant override of this method in Connection as there
    * is only a small likelihood of needing it.
    *
    * ISSUE: Need a better name.
    *
-   * @return this OperationGroup
+   * @return the same Submission that was returned by {@link OperationGroup#submitHoldingForMoreMembers}
    * @throws IllegalStateException if this {@link OperationGroup} has been
    * completed or is not held.
    */
-  public OperationGroup<S, T> releaseProhibitingMoreMembers();
+  public Submission<T> releaseProhibitingMoreMembers();
 
   /**
    * Provides a {@link Collector} to reduce the results of the member
@@ -276,7 +272,7 @@
   }
 
   /**
-   * Return a new {@link ArrayCountOperation}.
+   * Return a new {@link ArrayRowCountOperation}.
    * <p>
    * Usage Note: Frequently use of this method will require a type witness to
    * enable correct type inferencing.
@@ -287,30 +283,33 @@
    *     .submit ...
    * </code></pre>
    *
-   * @param <R> the result type of the returned {@link ArrayCountOperation}
+   * @param <R> the result type of the returned {@link ArrayRowCountOperation}
    * @param sql SQL to be executed. Must return an update count.
-   * @return a new {@link ArrayCountOperation} that is a member of this
+   * @return a new {@link ArrayRowCountOperation} that is a member of this
    * {@link OperationGroup}
    * @throws IllegalStateException if the {@link OperationGroup} has been
    * submitted and is not held
    */
-  public <R extends S> ArrayCountOperation<R> arrayCountOperation(String sql);
+  public <R extends S> ArrayRowCountOperation<R> arrayRowCountOperation(String sql);
 
   /**
-   * Return a new {@link CountOperation}.
+   * Return a new {@link ParameterizedRowCountOperation}.
    *
    * @param <R> the result type of the returned {@link CountOperation}
    * @param sql SQL to be executed. Must return an update count.
-   * @return an new {@link CountOperation} that is a member of this
+   * @return an new {@link ParameterizedRowCountOperation} that is a member of this
    * {@link OperationGroup}
    * @throws IllegalStateException if the {@link OperationGroup} has been
    * submitted and is not held
    */
-  public <R extends S> ParameterizedCountOperation<R> countOperation(String sql);
+  public <R extends S> ParameterizedRowCountOperation<R> rowCountOperation(String sql);
 
   /**
    * Return a new {@link Operation} for a SQL that doesn't return any result,
    * for example DDL. The result of this Operation is always null.
+   * 
+   * The result of the returned Operation must be Void but specifying that here
+   * causes problems.
    *
    * @param sql SQL for the {@link Operation}.
    * @return a new {@link Operation} that is a member of this
@@ -350,18 +349,18 @@
   public <R extends S> ParameterizedRowOperation<R> rowOperation(String sql);
 
   /**
-   * Return a new {@link RowProcessorOperation} that is a member {@link Operation} 
-   * of this {@link OperationGroup}.
-   * 
+   * Return a new {@link ParameterizedRowPublisherOperation} that is a member
+   * {@link Operation} of this {@link OperationGroup}.
+   *
    * @param <R> the type of the result of the returned
-   * {@link RowProcessorOperation}
+   * {@link ParameterizedRowPublisherOperation}
    * @param sql SQL for the {@link Operation}. Must return a row sequence.
-   * @return a new {@link RowProcessorOperation} that is a member of this
-   * {@link OperationGroup}
+   * @return a new {@link ParameterizedRowPublisherOperation} that is a member
+   * of this {@link OperationGroup}
    * @throws IllegalStateException if the {@link OperationGroup} has been
    * submitted and is not held
    */
-  public <R extends S> RowProcessorOperation<R> rowProcessorOperation(String sql);
+  public <R extends S> ParameterizedRowPublisherOperation<R> rowPublisherOperation(String sql);
 
   /**
    * Return a new {@link MultiOperation} that is a member 
@@ -383,6 +382,11 @@
    * transaction is ended with a commit unless the {@link Transaction} has been
    * {@link Transaction#setRollbackOnly} in which case the transaction is ended
    * with a rollback.
+   * 
+   * <p>
+   * An endTransaction Operation may be skipped. To insure that it will not be
+   * skipped it should immediately follow a catch Operation. All end transaction
+   * convenience methods do so.</p>
    *
    * The type argument {@link S} of the containing {@link OperationGroup} must
    * be a supertype of {@link TransactionOutcome}.
@@ -398,7 +402,8 @@
   /**
    * Convenience method that creates and submits a endTransaction
    * {@link Operation} that commits by default but can be set to rollback by
-   * calling {@link Transaction#setRollbackOnly}.
+   * calling {@link Transaction#setRollbackOnly}. The endTransaction Operation
+   * is never skipped.
    *
    * @param trans the Transaction that determines whether the {@link Operation} is a
    * database commit or a database rollback.
@@ -407,6 +412,7 @@
    * submitted and is not held or is parallel.
    */
   public default CompletionStage<TransactionOutcome> commitMaybeRollback(Transaction trans) {
+    catchErrors();
     return this.endTransactionOperation(trans).submit().getCompletionStage();
   }
 
@@ -422,44 +428,6 @@
   public <R extends S> LocalOperation<R> localOperation();
 
   /**
-   * Returns a Flow.Processor that subscribes to a sequence of Operations and
-   * produces a sequence of corresponding Submissions.The Operations must be
-   * members of this OperationGroup. Calling Subscription.onNext with any
-   * Operation that is not a member of this OperationGroup, that is was not
-   * created by calling one of the Operation factory methods on this
-   * OperationGroup, will cause the Subscription to be canceled and call
-   * Subscriber.onError with IllegalArgumentException. The method
-   * Subscription.onNext will call submit on each Operation it is passed and
-   * publish the resulting Submission. Since an Operation can only be submitted
-   * once, submitting an Operation and calling onNext with that submitted
-   * Operation will cause the Subscription to be canceled and Subscriber.onError
-   * to be called with IllegalStateException. The Processor does not retain
-   * Submissions to produce to a subsequently attached Subscriber.
-   *
-   * If there is no Subscriber to the Processor, the Processor will request
-   * Operations as appropriate. If there is a Subscriber to the Processor, the
-   * Processor will request Operations no faster than the Subscriber requests
-   * Submissions.
-   *
-   * Each call to this method returns a new Flow.processor. The Submissions
-   * published to each Processor are exactly those generated by calling submit
-   * on the Operations passed as arguments to onNext on the same Processor.
-   * Calling this method while there is an active Processor will throw
-   * IllegalStateException.
-   *
-   * Note: If any Operation is submitted directly, that is by calling submit
-   * rather than passing it to onNext, the Submission returned by the submit
-   * call will not be published.
-   *
-   * @param <R>
-   * @return a Flow.Processor that accepts {@link Operation}s and generates 
-   * {@link Submission}s
-   * @throws IllegalStateException if there is an active Processor or if this
-   * {@link OperationGroup} is submitted and not held
-   */
-  public <R extends S> Flow.Processor<Operation<R>, Submission<R>> operationProcessor();
-
-  /**
    * Supply a {@link Logger} for the implementation of this
    * {@link OperationGroup} to use to log significant events. Exactly what
    * events are logged, at what Level the events are logged and with what
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OutOperation.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OutOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,7 @@
    * @throws IllegalStateException if this method has been called previously on
    * this {@link Operation} or this {@link Operation} has been submitted.
    */
-  public OutOperation<T> apply(Function<Result.OutParameterMap, ? extends T> processor);
+  public OutOperation<T> apply(Function<Result.OutColumn, ? extends T> processor);
 
   // Covariant overrides
   
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedOperation.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowCountOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.concurrent.CompletionStage;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * A {@link ParameterizedRowCountOperation} is a {@link ParameterizedOperation} that returns a count.
+ *
+ * @param <T> the type of the result of this {@link Operation}
+ */
+public interface ParameterizedRowCountOperation<T> extends ParameterizedOperation<T>, RowCountOperation<T> {
+  
+  /**
+   * Returns a {@link RowOperation} to process the auto-generated keys, if any, returned
+   * by this {@link Operation}. If no keys are named the columns of the returned
+   * rows are implementation dependent. If keys are specified the columns of the
+   * returned rows are the keys. The {@link RowOperation} must be submitted before this 
+   * {@link Operation} is submitted. If it has not submitting this {@link Operation} will
+   * result throw {@link IllegalStateException}.
+   * 
+   * ISSUE: Should this be in {@link RowCountOperation}?
+   * 
+   * @param keys the names of the returned columns or null.
+   * @return A RowOperation that will process the auto-generated keys
+   * @throws IllegalStateException if this method has already been called on this
+   * {@link Operation} or if this {@link Operation} has already been submitted.
+   */
+  public RowOperation<T> returning(String ... keys);
+  
+  // Covariant overrides
+  
+  @Override
+  public ParameterizedRowCountOperation<T> onError(Consumer<Throwable> handler);
+  
+  @Override
+  ParameterizedRowCountOperation<T> apply(Function<Result.RowCount, ? extends T> processor);
+  
+  @Override
+  public ParameterizedRowCountOperation<T> set(String id, Object value);
+
+  @Override
+  public ParameterizedRowCountOperation<T> set(String id, Object value, SqlType type);
+
+  @Override
+  public ParameterizedRowCountOperation<T> set(String id, CompletionStage<?> source);
+
+  @Override
+  public ParameterizedRowCountOperation<T> set(String id, CompletionStage<?> source, SqlType type);
+
+  @Override
+  public ParameterizedRowCountOperation<T> timeout(Duration minTime);
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowOperation.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
   public ParameterizedRowOperation<T> fetchSize(long rows) throws IllegalArgumentException;
   
   @Override
-  public <A, S extends T> ParameterizedRowOperation<T> collect(Collector<? super Result.Row, A, S> c);
+  public <A, S extends T> ParameterizedRowOperation<T> collect(Collector<? super Result.RowColumn, A, S> c);
 
   @Override
   public ParameterizedRowOperation<T> set(String id, Object value, SqlType type);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedRowPublisherOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Flow;
+import java.util.function.Consumer;
+
+/**
+ * An Operation that accepts parameters, subscribes to a sequence of rows, and 
+ * returns a result.
+ * 
+ * @param <T> the type of the result of this {@link Operation}
+ */
+public interface ParameterizedRowPublisherOperation<T> 
+        extends RowPublisherOperation<T>, ParameterizedOperation<T> {
+
+  // Covariant overrides
+  
+  @Override
+  public ParameterizedRowPublisherOperation<T> subscribe(Flow.Subscriber<? super Result.RowColumn> subscriber,
+                                                          CompletionStage<? extends T> result);
+  
+  @Override
+  public ParameterizedRowPublisherOperation<T> set(String id, Object value, SqlType type);
+
+  @Override
+  public ParameterizedRowPublisherOperation<T> set(String id, CompletionStage<?> source, SqlType type);
+
+  @Override
+  public ParameterizedRowPublisherOperation<T> set(String id, CompletionStage<?> source);
+
+  @Override
+  public ParameterizedRowPublisherOperation<T> set(String id, Object value);
+
+  @Override
+  public ParameterizedRowPublisherOperation<T> onError(Consumer<Throwable> handler);
+  
+  @Override
+  public ParameterizedRowPublisherOperation<T> timeout(Duration minTime);
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/PrimitiveOperation.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/PrimitiveOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -35,8 +35,8 @@
  * class of errors. The two types are not distinguished in the JavaDoc as making 
  * such a distinction would not add clarity.
  * 
- * @see  Operation
- * @see  OperationGroup#catchOperation
+ * @see Operation
+ * @see OperationGroup#catchOperation
  */
 public interface PrimitiveOperation<T> {
 
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,16 +22,16 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package jdk.incubator.sql2;
 
-package jdk.incubator.sql2;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.function.Consumer;
 
 /**
- * All or part of the result of a database operation (lower case).
- *
- * A {@link Result} is valid only for the duration of the call it is passed to. Once
- * that call has returned, the {@link Result} passed to that call is invalid and any
- * calls to it throw {@link IllegalStateException}. {@link Result}s are not required to be
- * thread-safe.
  *
  */
 public interface Result {
@@ -39,96 +39,273 @@
   /**
    * A {@link Result} that is just a number of rows modified, a {@link Long}.
    *
-   * Note: It is certainly true that this is not needed; {@link Long} could be used
-   * instead. Seems like there might be a documentational advantage to having
-   * this type. If you don't like it, just mentally replace it with {@link Long}
-   * everywhere it appears.
+   * Note: It is certainly true that this is not needed; {@link Long} could be
+   * used instead. Seems like there might be a documentational advantage to
+   * having this type. If you don't like it, just mentally replace it with
+   * {@link Long} everywhere it appears.
    */
-  public static interface Count extends Result {
+  public static interface RowCount extends Result {
 
     /**
      *
-     * @return The number of rows returned
+     * @return
      */
     public long getCount();
   }
 
   /**
-   * A {@link Result} where the components can be retrieved by name. What 
-   * constitutes a name is implementation dependent.
-   *
+   * A mutable handle to one value of an ordered sequence of columns of a row or
+   * of out parameters. Columns have a 1-based index and optionally an
+   * identifier. Identifiers are not guaranteed to be unique. Only {@code clone}
+   * and {@code slice} create new instances. All other methods return this
+   * instance (modifying it if necessary) including {@code forEach},
+   * {@code next}, and {@code iterator}.
    */
-  public static interface ResultMap extends Result {
+  public interface Column extends Result, Iterable<Column>, Iterator<Column>, Cloneable {
+
+    /**
+     * Return the value of this column as an instance of the given type.
+     *
+     * @param <T>
+     * @param type
+     * @return the value of this {@link Column}
+     */
+    public <T> T get(Class<T> type);
+
+    /**
+     * Return the value of this {@link Column} as an instance of the default
+     * Java type for this column.
+     *
+     * @param <T>
+     * @return the value of this {@link Column}
+     */
+    public default <T> T get() {
+      return get(javaType());
+    }
+
+    /**
+     * Return the identifier of this {@link Column}. May be null.
+     *
+     * @return the identifier of this {@link Column}. May be null
+     */
+    public String identifier();
+
+    /**
+     * Return the 1-based index of this {@link Column}. The returned value is
+     * relative to the slice if this {@link Column} is the result of a call to
+     * {@code slice()}. {@code
+     * col.slice(n).index() == 1}.
+     *
+     * @return the index of this {@link Column}
+     */
+    public int index();
+
+    /**
+     * Return the 1-based index of this {@link Column} relative to the original
+     * sequence of values.
+     * {@code col.absoluteIndex() == col.slice(n).absoluteIndex()}.
+     *
+     * @return the absolute 1-based index of this {@link Column}
+     */
+    public int absoluteIndex();
+
+    /**
+     * Return the SQL type of the value of this {@link Column}.
+     *
+     * @return the SQL type of this value
+     */
+    public SqlType sqlType();
+
+    /**
+     * Return the Java type that best represents the value of this
+     * {@link Column}.
+     *
+     * @param <T>
+     * @return a {@link Class} that best represents the value of this
+     * {@link Column}
+     */
+    public <T>Class<T> javaType();
+
+    /**
+     * The length of the current value if defined.
+     *
+     * @return
+     * @throws UnsupportedOperationException if the length of the current value
+     * is undefined
+     */
+    public long length();
+
+    /**
+     * Return the number of remaining values accessible by this {@link Column}
+     * excluding the current value. This is the number of times {@code next()}
+     * can be called before {@code hasNext()} returns false.
+     *
+     * @return the number of values remaining
+     */
+    public int numberOfValuesRemaining();
 
     /**
-     * Return the value indicated by the {@code id}. The {@code id} may be either the id for an
-     * OUT parameter marker or for a column. See {@link OutOperation} and
-     * {@link RowOperation}.
+     * Modify this {@link Column} to point to a value identified by id.
+     *
+     * @apiNote The value specified for {@code id} represents the name of a
+     * column or parameter marker for the underlying data source and is
+     * implementation specific. This may be a simple SQL identifier, a quoted
+     * identifier, or any other type of identifier supported by the data source.
+     * <p>
+     * Consult your implementation&#39;s documentation for additional
+     * information.
+     *
+     * @param id an identifier. Not null
+     * @return this {@link Column}
+     * @throws NoSuchElementException if id does not identify exactly one value
+     */
+    public Column at(String id);
+
+    /**
+     * Modify this {@link Column} to point to the value at {@code index}. The
+     * first value is at index 1. Negative numbers count back from the last
+     * value. The last value is at index -1.
      *
-     * @param <T> the type of the returned value
-     * @param id the name of the column or OUT parameter marker
-     * @param type the value indicated by {@code id} is converted to this type
-     * @return a value of type {@code T}
-     * @throws IllegalArgumentException if id is not the identifier of a value
-     * in this {@link ResultMap}
-     * @throws IllegalStateException if the call that was passed this {@link ResultMap} has
-     * ended
-     * @throws ClassCastException if the returned value cannot be converted to the 
-     * specified type -- ISSUE: Not really a class cast. Maybe a new unchecked exception.
+     * @param index a new index
+     * @return this {@link Column}
+     * @throws NoSuchElementException if {@code index > length} or
+     * {@code index < -length}
      */
-    public <T> T get(String id, Class<T> type);
+    public Column at(int index);
+
+    /**
+     * Modify this {@link Column} to point to the value at the current index +
+     * {@code offset}. If {@code offset} is 0 this is a noop. If {@code offset}
+     * is negative the new index is less than the current index. If the new
+     * index would be less than 1 or greater than length this {@link Column} is
+     * not modified and {@link IllegalArgumentException} is thrown.
+     *
+     * @param offset an increment to the current index
+     * @return this {@link Column}
+     * @throws NoSuchElementException if the new index would be less than 1 or
+     * greater than {@code length}
+     */
+    public default Column next(int offset) {
+      int newIndex = index() + offset;
+      if (offset > numberOfValuesRemaining() || newIndex < 1) {
+        throw new NoSuchElementException();
+      }
+      return at(newIndex);
+    }
 
     /**
-     * Returns a {@code {@link String}[]} that contains the identifiers that reference the
-     * values of this {@link ResultMap} in the same order these values are returned by the
-     * database. A {@code null} value in the array means there is a returned value for
-     * which no identifier was defined. There is no way to retrieve such a
-     * value.
+     * Return a new {@link Column} that is a handle to a subsequence of the
+     * sequence of values referenced by this {@link Column}. The subsequence
+     * consists of {@code numValues} number of values. If {@code numValues} is
+     * positive the values are the value of this column and its successors. If
+     * {@code numValues} is negative the values are the predecessors of this
+     * column not including this {@link Column}. The order of the values of the
+     * new {@link Column} is the same as the order of the values of this
+     * {@link Column}. The returned {@link Column} points to the first value of
+     * the slice. This {@link Column} is not modified.
+     *
+     * @param numValues the number of columns to include in the slice
+     * @return a new {@link Column}.
+     * @throws NoSuchElementException if the current index plus
+     * {@code numValues} is greater than the number of values of this
+     * {@link Column} or less than 1
+     */
+    public Column slice(int numValues);
+
+    /**
+     * Return a new {@link Column} that is a duplicate of this {@link Column}.
+     * This {@link Column} is not modified.
+     *
+     * @return a new {@link Column}
+     */
+    public Column clone();
+
+    /**
+     * Modify this {@link Column} to point to the next value in the sequence.
      *
-     * By default the values in the array are the identifier portion of the out
-     * parameter markers in the SQL. Alternatively the implementation may assign
-     * other identifiers, typically column names or aliases. If there
-     * are values that have no associated identifier the corresponding value in
-     * the array will be null.
+     * @return this {@link Column}
+     * @throws NoSuchElementException if the new index would be greater than
+     * {@code length}
+     */
+    @Override
+    public default Column next() {
+      return next(1);
+    }
+
+    @Override
+    public default boolean hasNext() {
+      return numberOfValuesRemaining() > 0;
+    }
+
+    @Override
+    public default void forEach(Consumer<? super Column> action) {
+      do {
+        action.accept(this);
+      } while (hasNext());
+    }
+
+    @Override
+    public default Column iterator() {
+      return this;
+    }
+
+    /**
+     * TODO This almost certainly works correctly but it doesn't integrate well
+     * with the other access patterns. A better approach would be a Spliterator
+     * that overrides trySplit and creates new slices for each batch.
      *
-     * @return an array containing the value identifiers. Not {@code null}.
-     * @throws IllegalStateException if the call that was passed this {@link ResultMap} has
-     * ended
+     * There is a fundamental problem with mixing Spliterator with the other
+     * access patterns. The other patterns assume navigation from one column to
+     * an arbitrary other column. Spliterator.trySplit can divide the column
+     * sequence in arbitrary places invalidating the assumption about column
+     * navigation.
+     *
+     * @return a {@link java.util.Spliterator}
      */
-    public String[] getIdentifiers();
+    @Override
+    public default Spliterator<Column> spliterator() {
+      List list = new ArrayList<>(numberOfValuesRemaining());
+      this.clone().forEach(c -> list.add(c.slice(1)));
+      return java.util.Spliterators.spliterator(list.toArray(), numberOfValuesRemaining());
+    }
   }
 
   /**
-   * Used by {@link OutOperation} to expose the out parameters of a call.
+   * Used by {@link OutOperation} to expose the out parameters of a stored
+   * procedure call.
+   *
+   * This exists to allow for future additions.
    */
-  public static interface OutParameterMap extends ResultMap {
+  public interface OutColumn extends Column {
+
   }
 
   /**
    * Used by {@link RowOperation} to expose each row of a row sequence.
    */
-  public static interface Row extends ResultMap {
+  public static interface RowColumn extends Column {
 
     /**
-     * The count of {@link Row}s in the {@link Row} sequence preceeding this {@link Row}. For the first
-     * row in the Row sequence the {@link rowNumber} is 0.
+     * The count of rows in the row sequence preceeding this {@link RowColumn}.
+     * For the first row in the row sequence the {@code rowNumber} is 0.
      *
-     * @return the count of {@link Row}s in the {@link Row} sequence preceeding this {@link Row}
-     * @throws IllegalStateException if the call that was passed this {@link Result} has
-     * ended
+     * @return the count of rows in the row sequence preceeding this
+     * {@link RowColumn}
+     * @throws IllegalStateException if the call that was passed this
+     * {@link Result} has ended
      */
     public long rowNumber();
 
     /**
-     * Terminate processing of the rows in this {@link RowOperation}. The result of the
-     * call that was passed this {@link Row} will be the result of the {@link Operation}. No
-     * further rows in the row sequence will be processed. All subsequent rows,
-     * if any, will be ignored. Any rows already fetched will not be processed.
-     * Any rows not yet fetched may or may not be fetched. If fetched they will
-     * not be processed.
+     * Terminate processing of the rows in this {@link RowOperation}. No further
+     * rows in the row sequence will be processed. All subsequent rows, if any,
+     * will be ignored. Any rows already fetched will not be processed. Any rows
+     * not yet fetched may or may not be fetched. If fetched they will not be
+     * processed. The RowOperation will be completed normally, as though the
+     * current row were the last row of the row sequence.
      *
-     * @throws IllegalStateException if the call that was passed this {@link Result} has
-     * ended
+     * @throws IllegalStateException if the call that was passed this
+     * {@link RowColumn} has ended
      */
     public void cancel();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowCountOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * An {@link Operation} that returns a count.
+ *
+ * @param <T> the type of the result of the {@link Operation}
+ * @see ParameterizedCountOperation
+ */
+public interface RowCountOperation<T> extends Operation<T> {
+
+  /**
+   * Sets the result processor for this {@link Operation}.
+   * 
+   * @param function processes the count produced by executing this
+   * {@link Operation} and returns the result
+   * @return this {@link RowCountOperation}
+   * @throws IllegalStateException if this method has been called previously
+   */
+  public RowCountOperation<T> apply(Function<Result.RowCount, ? extends T> function);
+
+  @Override
+  public RowCountOperation<T> onError(Consumer<Throwable> handler);
+
+  @Override
+  public RowCountOperation<T> timeout(Duration minTime);
+  
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowOperation.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,9 @@
 
 package jdk.incubator.sql2;
 
+import java.util.function.BiConsumer;
 import java.util.function.Consumer;
+import java.util.function.Supplier;
 import java.util.stream.Collector;
 
 /**
@@ -63,7 +65,21 @@
    * @throws IllegalStateException if this method had been called previously or
    * this Operation has been submitted.
   */
-  public <A, S extends T> RowOperation<T> collect(Collector<? super Result.Row, A, S> c);
+  public <A, S extends T> RowOperation<T> collect(Collector<? super Result.RowColumn, A, S> c);
+  
+  /**
+   * Convenience method to collect the rows when the accumulated result is the 
+   * final result.
+   * 
+   * @param <S> the type of the accumulated result
+   * @param supplier supplies the accumulated result
+   * @param accumulator accumulates each RowColumn into the accumulated result
+   * @return this RowOperation
+   */
+  public default <S extends T> RowOperation<T> collect(Supplier<S> supplier,
+                                 BiConsumer<S, Result.RowColumn> accumulator) {
+    return collect(Collector.of(supplier, accumulator, (l, r) -> l));
+  }
 
   @Override
   public RowOperation<T> onError(Consumer<Throwable> handler);
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowProcessorOperation.java	Wed Jun 20 15:12:52 2018 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-/*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- * 
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- * 
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- * 
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- * 
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.incubator.sql2;
-
-import java.time.Duration;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.Flow;
-import java.util.function.Consumer;
-
-/**
- * A RowProcessorOperation handles a database action that returns a sequence of 
- * rows. The rows are handled by a java.util.concurrent.Flow.Processor. A 
- * RowProcessorOperation is conceptually a Row Publisher and a result Subscriber.
- * The configured Processor transforms the Row stream into a result stream.
- * Configuring a Processor causes the RowProcessorOperation to subscribe the
- * Processor to the stream of rows and for the RowProcessorOperation itself to 
- * subscribe to the stream of results published by the Processor. The last
- * result produced is the result of the RowProcessorOperation.
- * 
- * The RowProcessorOperation will insure that the demand for results is positive.
- * 
- * Calling Submission.cancel will call cancel on the result Subscription. The
- * Processor should call cancel on the row Subscription when cancel is called on
- * the result Subscription.
- * 
- * @param <T> the type of the result of the {@link Operation}
- */
-public interface RowProcessorOperation<T> extends ParameterizedOperation<T> {
-
-  /** DRAFT
-   * Accepts a Processor that subscribes to a stream of Rows and publishes
-   * a stream of result values. This Operation will subscribe to the stream of
-   * results. The last published result value is the result of the
-   * Operation.
-   * 
-   * This Operation will insure result demand is eventually positive until 
-   * resultSubscriber.onComplete or resultSubscriber.onError is called. This 
-   * Operation will call resultSubscription.cancel if this Operation is canceled.
-   * 
-   * While there are more rows and row demand is positive and rowSubscription.cancel
-   * has not been called, this Operation will eventually call rowToResult.onNext
-   * with the next row in the row sequence. The Result.Row argument to onNext is
-   * only valid for the duration of that call. When there are no more Rows this 
-   * Operation will call rowToResult.onComplete. If there is an error this
-   * Operation will call rowToResult.onError with the appropriate Exception whether
-   * or not any rows were published.
-   *
-   * If resultSubscriber.onError is called this Operation completes
-   * exceptionally with the passed exception. After all rows are published if
-   * neither resultSubscriber.onComplete or resultSubscriber.onError is
-   * called this Operation will complete exceptionally after the inactivity
-   * timeout expires.
-   * 
-   * If this Operation is skipped it will be completed exceptionally with
-   * SqlSkippedException but no calls will be made to rowToResult.
-   * 
-   * Calling Row.cancel is the same as calling Subscription.cancel on the Row
-   * Subscription.
-   *
-   * @param rowToResult subscribes to a stream of Result.Rows and publishes a
-   * stream of results of type T
-   * @return this RowProcessorOperation
-   */
-  public RowProcessorOperation<T> rowProcessor(Flow.Processor<Result.Row, ? extends T> rowToResult);
-  
-  /** DRAFT 
-   * Subscribe to the stream of Rows returned by this Operation. The result of 
-   * this Operation is null. This is a convenience method.
-   * 
-   * @param rowSubscriber subscribes to a stream of Result.Rows 
-   * @return this RowProcessorOperation
-   */
-  public default RowProcessorOperation<T> subscribe(Flow.Subscriber<Result.Row> rowSubscriber) {
-
-    // create a Row to result Processor that passes the Rows to rowSubscriber
-    // and publishes a single null as its only result.
-    Flow.Processor<Result.Row, T> rowToResult
-            = new Flow.Processor<Result.Row, T>() {
-
-      protected boolean isResultPending = false;
-      protected long resultDemand = 0;
-
-      protected Flow.Subscription rowSubscription;
-
-      protected Flow.Subscriber<? super T> resultSubscriber;
-
-      protected Flow.Subscription resultSubscription = new Flow.Subscription() {
-        @Override
-        public void request(long n) {
-          resultDemand += n;
-          if (isResultPending && resultDemand > 0) {
-            resultSubscriber.onNext(null);
-            resultDemand--;
-            resultSubscriber.onComplete();
-            isResultPending = false;
-          }
-        }
-
-        @Override
-        public void cancel() {
-          rowSubscription.cancel();
-        }
-      };
-
-      @Override
-      public void onSubscribe(Flow.Subscription subscription) {
-        rowSubscription = subscription;
-        rowSubscriber.onSubscribe(rowSubscription);
-
-      }
-
-      @Override
-      public void onNext(Result.Row item) {
-        rowSubscriber.onNext(item);
-      }
-
-      @Override
-      public void onError(Throwable throwable) {
-        rowSubscriber.onError(throwable);
-        resultSubscriber.onError(throwable);
-      }
-
-      @Override
-      public void onComplete() {
-        rowSubscriber.onComplete();
-        if (resultDemand > 0) {
-          resultSubscriber.onNext(null);
-          resultSubscriber.onComplete();
-        } else {
-          isResultPending = true;
-        }
-      }
-
-      @Override
-      public void subscribe(Flow.Subscriber<? super T> subscriber) {
-        resultSubscriber = subscriber;
-        resultSubscriber.onSubscribe(resultSubscription);
-      }
-    };
-
-    return rowProcessor(rowToResult);
-  }
-
-  /** DRAFT
-   * Sets the minimum time the Operation will wait for Processor activity before
-   * terminating. If all of the following hold for some time exceeding minTime,
-   * this Operation will be completed exceptionally with 
-   * {@link java.util.concurrent.TimeoutException}.
-   * <ul>
-   * <li>no calls to the onNext, onComplete, or onError methods of the result
-   * Subscriber, ie the Subscriber passed to rowToResult.subscribe</li>
-   * <li>the demand for Rows is zero or all rows have been published</li>
-   * </ul>
-   * If the Operation can publish no more rows either because all rows have
-   * been published or because the demand for rows is 0 and rowToResult
-   * has neither published a result nor terminated the stream and this state has
-   * continued for at least minTime, the Operation is completed exceptionally.
-   * 
-   * The default value is one minute.
-   * 
-   * Note: The minTime parameter value must be small to guarantee that the 
-   * Connection does not hang for long periods. The default is large enough
-   * that it most likely is insignificant for most apps, but small enough to
-   * kick loose a hung Connection in semi-reasonable time.
-   * 
-   * @param minTime minimum time with the Processor making no progress before the
-   * Operation is terminated.
-   * @return this RowProcessorOperation
-   */
-  public RowProcessorOperation<T> inactivityTimeout(Duration minTime);
-  
-  
-  // Covariant overrides
-  
-  @Override
-  public RowProcessorOperation<T> onError(Consumer<Throwable> handler);
-  
-  @Override
-  public RowProcessorOperation<T> set(String id, Object value, SqlType type);
-
-  @Override
-  public RowProcessorOperation<T> set(String id, CompletionStage<?> source, SqlType type);
-
-  @Override
-  public RowProcessorOperation<T> set(String id, CompletionStage<?> source);
-
-  @Override
-  public RowProcessorOperation<T> set(String id, Object value);
-
-  @Override
-  public RowProcessorOperation<T> timeout(Duration minTime);
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/RowPublisherOperation.java	Wed Jun 20 15:38:40 2018 -0400
@@ -0,0 +1,33 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package jdk.incubator.sql2;
+
+import java.time.Duration;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Flow;
+import java.util.function.Consumer;
+
+public interface RowPublisherOperation<T> extends Operation<T> {
+
+  /**
+   * * DRAFT Subscribe to the stream of Rows returned by this Operation. The
+   * result of this Operation is the value of the {@code result} parameter.
+   *
+   * @param subscriber Not null.
+   * @param result Not null.
+   * @return this RowPublisherOperation
+   */
+  public RowPublisherOperation<T> subscribe(Flow.Subscriber<? super Result.RowColumn> subscriber,
+                                            CompletionStage<? extends T> result);
+  // Covariant overrides
+  
+  @Override
+  public RowPublisherOperation<T> onError(Consumer<Throwable> handler);
+  
+  @Override
+  public RowPublisherOperation<T> timeout(Duration minTime);
+  
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ShardingKey.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ShardingKey.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  * 
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlArray.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlArray.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  * 
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlBlob.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlBlob.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlClob.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlClob.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlColumns.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlColumns.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlException.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlException.java	Wed Jun 20 15:38:40 2018 -0400
@@ -72,6 +72,14 @@
   private final int position;
   
   // Constructors
+  
+  public SqlException(Throwable ex) {
+    super(ex);
+    this.sqlState = null;
+    this.vendorCode = -1;
+    this.sqlString = null;
+    this.position = -1;
+  }
 
   /**
    *
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlParameter.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlParameter.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlRef.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlRef.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  * 
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 
 /**
  *
- * @param <T> the type of SQL REF
+ * @param <T>
  */
 public interface SqlRef<T> {
   
@@ -38,7 +38,7 @@
    * ISSUE: Oracle Database JDBC driver may do a round trip for this. Is this
    * that heavy in other databases?
    * 
-   * @return the fully-qualified SQL name of the referenced SQL structured type
+   * @return
    */
   public String getReferentTypeName();
   
@@ -64,8 +64,7 @@
    * Create and return an Operation that will set the value of the REF in the
    * database.
    *
-   * @param value an Object representing the SQL structured type instance
-   * that this Ref object will reference
+   * @param value
    * @return an Operation that will store the new referent into the REF
    */
   public Operation<Void> storeOperation(T value);
@@ -74,8 +73,7 @@
    * Submit an Operation that will store the new value of the referent into
    * the REF in the database.
    *
-   * @param value an Object representing the SQL structured type instance
-   * that this Ref object will reference
+   * @param value
    * @return a Future that will complete when the submitted Operation completes.
    */
   public default CompletionStage<Void> store(T value) {
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlStruct.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlStruct.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  * 
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlType.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlType.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,32 +26,31 @@
 package jdk.incubator.sql2;
 
 /**
- * An object that is used to identify a generic SQL type, called a JDBC type or
- * a vendor specific data type.
- *
- * @since 1.8
+ * Remove dependence on java.sql.
  */
 public interface SqlType {
 
-    /**
-     * Returns the {@code SQLType} name that represents a SQL data type.
-     *
-     * @return The name of this {@code SQLType}.
-     */
+  /**
+   *
+   * @return
+   */
   public String getName();
 
-    /**
-     * Returns the name of the vendor that supports this data type. The value
-     * returned typically is the package name for this vendor.
-     *
-     * @return The name of the vendor for this data type
-     */
+  /**
+   *
+   * @return
+   */
   public String getVendor();
 
-    /**
-     * Returns the vendor specific type number for the data type.
-     *
-     * @return An Integer representing the vendor specific data type
-     */
+  /**
+   *
+   * @return
+   */
   public Integer getVendorTypeNumber();
+  
+  /**
+   * 
+   * @return Java type
+   */
+  public <T> Class<T> getJavaType();
 }
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Submission.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Submission.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Transaction.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Transaction.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/TransactionOutcome.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/TransactionOutcome.java	Wed Jun 20 15:38:40 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c)  2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,11 @@
   UNKNOWN,
   
   /**
+   *  The outcome of the transaction is in doubt.
+   */
+  IN_DOUBT,
+  
+  /**
    * The transaction committed successfully.
    */
   COMMIT, 
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java	Wed Jun 20 15:12:52 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java	Wed Jun 20 15:38:40 2018 -0400
@@ -186,7 +186,7 @@
  * effort in an app using that feature only to discover in production that the
  * performance is unacceptable. For example, if an implementation can only support
  * {@link Operation#timeout} through active polling it would be better for that
- * implementation to throw  UnsupportedFeatureException if 
+ * implementation to throw  {@link UnsupportedOperationException} if 
  * {@link Operation#timeout} is called.</p>
  *
  * <h3>Execution Model</h3>
@@ -208,9 +208,9 @@
  * of the result processor if there is one or with the result of the action if
  * there is no result processor. If the action or the result processing causes
  * an unhandled error the {@link java.util.concurrent.CompletionStage} is
- * completed exceptionally. The CompletionStage is completed asynchronously,
- * as though it were created by calling an <i>async</i> method on 
- * CompletionStage.
+ * completed exceptionally. The {@link java.util.concurrent.CompletionStage} is
+ * completed asynchronously, as though it were created by calling an
+ * <i>async</i> method on {@link java.util.concurrent.CompletionStage}.
  * </p>
  *
  * <p>
@@ -232,7 +232,7 @@
  * If the {@link OperationGroup} has a condition, the value of the condition is
  * retrieved. If the value is {@link Boolean#FALSE} the action is complete and
  * the {@link java.util.concurrent.CompletionStage} is completed with null. If
- * the value completes exceptionally the action is complete and the
+ * the condition value completes exceptionally the action is complete and the
  * {@link java.util.concurrent.CompletionStage} is completed exceptionally
  * with the same exception. If the condition value is {@link Boolean#TRUE} or
  * there is no condition the {@link Operation}s in the collection are executed
@@ -240,26 +240,26 @@
  * {@link OperationGroup} is not held and all the {@link Operation}s have been
  * executed.</li>
  * <li>
- * If the {@link OperationGroup} is parallel more than one {@link Operation} may
- * be executed at a time.</li>
+ * If the {@link OperationGroup} is parallel more than one member
+ * {@link Operation} may be executed at a time.</li>
  * <li>
- * If the {@link OperationGroup} is dependent and an {@link Operation} completes
- * exceptionally all {@link Operation}s in the collection that are yet to begin
+ * If the {@link OperationGroup} is dependent and a member {@link Operation} completes
+ * exceptionally all member {@link Operation}s that are yet to begin
  * execution are completed exceptionally with a {@link SqlSkippedException}. The
  * cause of that exception is the {@link Throwable} that caused the
  * {@link Operation} to be completed exceptionally. If an {@link Operation} is
  * in flight when another {@link Operation} completes exceptionally the in
  * flight {@link Operation} may either be allowed to complete uninterrupted or
- * it may be completed exceptionally. The {@link OperationGroup} is completed
- * exceptionally with the {@link Throwable} that caused the {@link Operation} to
- * complete exceptionally. 
+ * it may be completed exceptionally. The {@link OperationGroup} is dependent it
+ * is completed exceptionally with the {@link Throwable} that caused the 
+ * {@link Operation} to complete exceptionally. 
  * 
  * <p>
  * Note: the {@link Operation}s returned by {@link Connection#closeOperation}
  * and {@link OperationGroup#catchOperation} are never skipped, i.e. never 
  * completed exceptionally with {@link SqlSkippedException}. The {@link Operation}
  * returned by {@link OperationGroup#catchOperation} never completes 
- * execeptionally so the following {@link Operation} is always executed normally. 
+ * exceptionally so the following {@link Operation} is always executed normally. 
  * No {@link Operation} can be submitted after the {@link Operation} returned by 
  * {@link Connection#closeOperation} has been submitted.</p> </li>
  * <li>
@@ -293,7 +293,7 @@
  * <p>
  * The creation of Operations and the subsequent execution of those Operations
  * are separated in time. It is quite reasonable to determine that a transaction
- * should commit after the Operation that ends the transaction is created.
+ * should commit after the Operation that ends the transaction is submitted.
  * But if the execution of the transaction does not result in the expected results
  * it might be necessary to rollback the transaction rather than commit it. This
  * determination depends on the execution of the Operations long after the
@@ -333,6 +333,64 @@
  * the transaction to rollback.</p>
  * 
  *
+ * <h3>Implementation Note</h3>
+ * 
+ * <p>
+ * If an implementation exposes any implementation specific types and methods, the
+ * implementation is expected to provide covariant overrides for all methods that
+ * return the standard super-type of the implementation specific type.</p>
+ * 
+ * <p>
+ * Consider an implementation that adds a method foo() to RowCountOperation. To do
+ * that it would have to expose a type FooRowCountOperation extends RowCountOperation.
+ * So that an application can transparently access foo, the implementation would
+ * also have to expose FooDataSource, FooOperationGroup and FooConnection. Further
+ * each of these types would have to declare covariant overrides for every method
+ * that returns a direct super-type of one of these types.</p>
+ * <ul>
+ * <li>FooDataSourceFactory must override builder to return FooDataSource.Builder</li>
+ * <li>FooDataSource.Builder must override url, password, etc to return a
+ * FooDataSource.Builder. build must return a FooDataSource.</li>
+ * <li>FooDataSource must override builder to return FooConnection.Builder</li>
+ * <li>FooConnection.Builder must override url, password, etc to return a 
+ * FooConnection.Builder. build must return a FooConnection</li>
+ * <li>FooDataSource must override getConnection to return FooConnection</li>
+ * <li>FooConnection must extend FooOperationGroup</li>
+ * <li>FooOperationGroup> must override rowCountOperation to return FooRowCountOperation</li>
+ * <li>FooRowCountOperation must override apply and onError to return FooRowCountOperation</li>
+ * </ul>
+ * <p>
+ * The intent is to transparently expose the vendor extension without use of casts.
+ * Example: </p>
+ * 
+ * <pre>
+ * {@code
+ *   FooDataSourceFactory factory = DataSourceFatory.newFactory("com.foo.FooDataSourceFatory");
+ *   FooDataSource dataSource = factory.builder()
+ *       .url("scott/tiger@host:port")
+ *       .build();
+ *   FooConnection conn = dataSource.getConnection();
+ *   CompletionStage<Long> count = conn.rowOperation(sql)
+ *       .set("param", value, AdbaType.VARCHAR)
+ *       .foo()
+ *       .submit()
+ *       .getCompletionStage();
+ * }
+ * </pre>
+ * 
+ * <p>
+ * Notice that there are no casts, yet both standard methods an the vendor extension
+ * method foo can be referenced. This is possible only if the implementation exposes
+ * all the necessary types and provides covariant overrides for every method that
+ * returns one of those types. Implementations are expected (required?) to do this.
+ * </p>
+ * 
+ * <p>
+ * If an implementation does not expose any implementation specific methods or 
+ * types, that implementation is not required to provide covariant overrides that
+ * return implementation specific types.</p>
+ * 
+ * 
  */
  package jdk.incubator.sql2;