JDK-8188051-branch latest updates JDK-8188051-branch
authorlancea
Mon, 09 Jul 2018 15:09:06 -0400
branchJDK-8188051-branch
changeset 56824 62e92191354d
parent 56823 6ba0dbf6a75f
child 56825 9715cfc63e06
JDK-8188051-branch latest updates
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaDataSourceProperty.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaSessionProperty.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaType.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Connection.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ConnectionProperty.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/DataSourceProperty.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Examples.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/LocalOperation.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedOperation.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/Session.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SessionProperty.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ShardingKey.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/SqlType.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Transaction.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/TransactionEnd.java
src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaDataSourceProperty.java	Mon Jul 09 15:09:06 2018 -0400
@@ -0,0 +1,77 @@
+/*
+ * 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.util.function.Function;
+
+/**
+ * Properties that apply to the DataSource as a whole, not to the individual
+ * {@link Session}s that the {@link DataSource} creates.
+ */
+public enum AdbaDataSourceProperty implements DataSourceProperty {
+  
+ 
+  MAX_RESOURCES(Integer.class,
+                v -> v instanceof Integer && (int) v >= 0,
+                Integer.MAX_VALUE,
+                false),
+  
+  MAX_IDLE_RESOURCES(Integer.class,
+                v -> v instanceof Integer && (int) v >= 0,
+                Integer.MAX_VALUE,
+                false);
+
+  private final Class<?> range;
+  private final Function<Object, Boolean> validator;
+  private final Object defaultValue;
+  private final boolean isSensitive;
+
+  private AdbaDataSourceProperty(Class<?> range, 
+          Function<Object, Boolean> validator,
+          Object value,
+          boolean isSensitive) {
+    this.range = range;
+    this.validator = validator;
+    this.defaultValue = value;
+    this.isSensitive = isSensitive;
+  }
+  
+  @Override
+  public Class<?> range() {
+    return range;
+  }
+
+  @Override
+  public Object defaultValue() {
+    return defaultValue;
+  }
+
+  @Override
+  public boolean isSensitive() {
+    return isSensitive;
+  }
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaSessionProperty.java	Mon Jul 09 15:09:06 2018 -0400
@@ -0,0 +1,222 @@
+/*
+ * 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.util.function.Function;
+import java.time.Duration;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ForkJoinPool;
+
+/**
+ * A set of {@link SessionProperty} commonly supported. Implementations are not
+ * required to support all of these properties.
+ */
+public enum AdbaSessionProperty implements SessionProperty {
+  
+  /**
+   *
+   */
+  CACHING(Caching.class, 
+          v -> v instanceof Caching,
+          Caching.AS_NEW,
+          false),
+  
+  /**
+   * 
+   */
+  COMMIT_ON_CLOSE(Boolean.class,
+                  v -> v instanceof Boolean,
+                  Boolean.FALSE,
+                  false),
+  
+  /**
+   *
+   */
+  EXECUTOR(Executor.class,
+           v -> v instanceof Executor,
+           ForkJoinPool.commonPool(),
+           false),
+
+  /**
+   *
+   */
+  NETWORK_TIMEOUT(Duration.class, 
+          v -> v instanceof Duration && ! ((Duration)v).isNegative(),
+          Duration.ofSeconds(Long.MAX_VALUE),
+          false),
+
+  /**
+   *
+   */
+  PASSWORD(String.class,
+          v -> v instanceof String,
+          null,
+          true),
+
+  /**
+   *
+   */
+  READ_ONLY(Boolean.class, 
+          v -> v instanceof Boolean,
+          false,
+          false),
+
+  /**
+   *
+   */
+  SHARDING_KEY(ShardingKey.class,
+          v -> v instanceof ShardingKey,
+          null,
+          false),
+
+  /**
+   *
+   */
+  SHARDING_GROUP_KEY(ShardingKey.class,
+          v -> v instanceof ShardingKey,
+          null,
+          false),
+
+  /**
+   *
+   */
+  TRANSACTION_ISOLATION(TransactionIsolation.class, 
+          v -> v instanceof TransactionIsolation,
+          TransactionIsolation.READ_COMMITTED,
+          false),
+
+  /**
+   *
+   */
+  URL(String.class,
+          v -> v instanceof String,
+          null,
+          false),
+
+  /**
+   *
+   */
+  USER(String.class,
+          v -> v instanceof String,
+          null,
+          false);
+
+  private final Class<?> range;
+  private final Function<Object, Boolean> validator;
+  private final Object defaultValue;
+  private final boolean isSensitive;
+
+  private AdbaSessionProperty(Class<?> range, 
+          Function<Object, Boolean> validator,
+          Object value,
+          boolean isSensitive) {
+    this.range = range;
+    this.validator = validator;
+    this.defaultValue = value;
+    this.isSensitive = isSensitive;
+  }
+
+  @Override
+  public Class<?> range() {
+    return range;
+  }
+
+  @Override
+  public boolean validate(Object value) {
+    return validator.apply(value);
+  }
+
+  @Override
+  public Object defaultValue() {
+    return defaultValue;
+  }
+
+  @Override
+  public boolean isSensitive() {
+    return isSensitive;
+  }
+
+  /**
+   * Specifies how much flexibility the {@link DataSource} has in satisfying a
+   * request for a {@link Session} possibly by using cached data source resources.
+   */
+  public enum Caching {
+    /**
+     * The returned {@link Session} is required to be backed by a completely new 
+     * data source resource configured exactly as specified by the other properties. Use this with caution and
+     * only when absolutely necessary. Use {@link AS_NEW} instead if at all possible.
+     * This should be used only to work around some limitation of the database
+     * or the implementation.
+     */
+    NEW,
+    /**
+     * The returned {@link Session} has no state other than that of a {@link Session}
+     * attached to a newly created data source resource modified as specified by 
+     * the other properties. May not be strictly new
+     * but has the same behavior as if it were. The {@link Session} 
+     * may be {@link NEW}. The default.
+     */
+    AS_NEW,
+    /**
+     * The returned {@link Session} has the state specified by the other properties
+     * but may have additional state that differs from that of a new {@link Session}.
+     * The {@link Session} may be {@link AS_NEW}.
+     */
+    CACHED;
+  }
+
+  /**
+   *
+   */
+  public enum TransactionIsolation {
+
+    /**
+     *
+     */
+    NONE,
+
+    /**
+     *
+     */
+    READ_COMMITTED,
+
+    /**
+     *
+     */
+    READ_UNCOMMITTED,
+
+    /**
+     *
+     */
+    REPEATABLE_READ,
+
+    /**
+     *
+     */
+    SERIALIZABLE;
+  }
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaType.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/AdbaType.java	Mon Jul 09 15:09:06 2018 -0400
@@ -204,6 +204,8 @@
      * Identifies the generic SQL type {@code TIMESTAMP WITH TIME ZONE}.
      */
     TIMESTAMP_WITH_TIME_ZONE(OffsetDateTime.class);
+    
+  private static final String STANDARD_VENDOR = "jdk.incubator.sql2";
 
   protected final Class javaType;
   
@@ -223,11 +225,11 @@
     /**
      * Returns the name of the vendor that supports this data type.
      * @return  The name of the vendor for this data type which is
-     * {@literal java.sql} for ABDAType.
+     * the package name containing this type.
      */
   @Override
   public String getVendor() {
-    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+    return STANDARD_VENDOR;
   }
 
     /**
@@ -236,11 +238,6 @@
      * the value will be the same value as in {@code Types} for the data type.
      */
   @Override
-  public Integer getVendorTypeNumber() {
-    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/Connection.java	Fri Jul 06 20:37:32 2018 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,614 +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.Map;
-import java.util.concurrent.CompletionStage;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-/**
- * A {@link Connection} is an abstraction of a connection to a SQL database and
- * a group of {@link Operation}s to be executed by that SQL database. No method
- * on {@link Connection} or any of its dependent objects ({@link RowOperation}
- * etc) blocks with the exception of those few methods with "Wait" in their
- * name. Any other method that might block must execute any potentially blocking
- * action in a thread other than the calling thread.
-
-* <p>
- * All methods inherited from OperationGroup throw IllegalStateException if the
- * the connection is not active.</p>
-
-* <p>
- * An implementation of this type must be thread safe as result and error
- * handlers running asynchronously may be accessing a {@link Connection} in
- * parallel with each other and with a user thread. {@link Connection}s are not
- * required to support multiplexed use; a single {@link Connection} should be
- * used for only one unit of work at a time. Executing independent units of work
- * on a single {@link Connection} in parallel will most likely lead to
- * unpredictable outcomes. As a rule of thumb only one user thread should access
- * a {@link Connection} at a time. Such a user thread should execute a complete
- * unit of work before another user thread accesses the {@link Connection}. An
- * implementation may support parallel multiplexed use, but it is not required.</p>
- */
-public interface Connection extends AutoCloseable, OperationGroup<Object, Object> {
-
-  /**
-   * Identifies the operational state of a {@link Connection}.
-   */
-  public enum Lifecycle {
-    /**
-     * unconnected. When a connect {@link Operation} is completed successfully
-     * -&gt; {@link OPEN}. If {@link deactivate} is called -&gt;
-     * {@link NEW_INACTIVE}. If {@link abort} is called -&gt; {@link ABORTING}.
-     * No {@link Operation}s other than connect and close will be performed. A
-     * Connection in this state is both 'open' and 'active'.
-     */
-    NEW,
-    /**
-     * Unconnected and inactive. Any queued connect or close {@link Operation}
-     * is performed. No work can be submitted. If the {@link activate} method is
-     * called -&gt; {@link NEW}. If a connect {@link Operation} completes -&gt;
-     * {@link INACTIVE}. If a close {@link Operation} is executed -&gt;
-     * {@link CLOSING}. If {@link abort} is called -&gt; {@link ABORTING}. A
-     * Connection in this state is 'open'.
-     */
-    NEW_INACTIVE,
-    /**
-     * fully operational. Work is queued and performed. If {@link deactivate} is
-     * called -&gt; {@link INACTIVE}. If a close {@link Operation} is executed
-     * -&gt; {@link CLOSING}. If {@link abort} is called -&gt; {@link ABORTING}.
-     * A Connection in this state is both 'open' and 'active'.
-     */
-    OPEN,
-    /**
-     * Not available for new work. Queued work is performed. No work can be
-     * submitted. If the {@link activate} method is called -&gt; {@link OPEN}.
-     * If a close {@link Operation} is executed -&gt; {@link CLOSING}. If
-     * {@link abort} is called -&gt; {@link ABORTING}. A {@link Connection} in
-     * this state is 'open'.
-     */
-    INACTIVE,
-    /**
-     * Work in progress is completed but no additional work is started or
-     * queued. Attempting to queue work throws {@link IllegalStateException}.
-     * When the currently executing {@link Operation}s are completed -&gt;
-     * {@link CLOSED}. All other queued Operations are completed exceptionally
-     * with SqlSkippedException. A Connection in this state is 'closed'.
-     */
-    CLOSING,
-    /**
-     * Work is neither queued nor performed. The currently executing
-     * {@link Operation}s, if any, are terminated, exceptionally if necessary.
-     * Any queued {@link Operation}s are terminated exceptionally with
-     * {@link SqlSkippedException}. Attempting to queue work throws
-     * {@link IllegalStateException}. When the queue is empty -&lt;
-     * {@link CLOSED}. A Connection in this state is 'closed'.
-     */
-    ABORTING,
-    /**
-     * Work is neither queued nor performed. Attempting to queue work throws
-     * {@link IllegalStateException}. A Connection in this state is 'closed'.
-     */
-    CLOSED;
-    
-    static {
-      NEW.init(true, true, NEW, NEW_INACTIVE, OPEN, ABORTING, CLOSING, CLOSED);
-      NEW_INACTIVE.init(true, false, NEW, NEW_INACTIVE, INACTIVE, ABORTING, CLOSING, CLOSED);
-      OPEN.init(true, true, OPEN, INACTIVE, OPEN, ABORTING, CLOSING, CLOSED);
-      INACTIVE.init(true, false, OPEN, INACTIVE, INACTIVE, ABORTING, INACTIVE, INACTIVE);
-      CLOSING.init(false, true, CLOSING, CLOSING, CLOSING, ABORTING, CLOSING, CLOSED);
-      ABORTING.init(false, true, ABORTING, ABORTING, ABORTING, ABORTING, ABORTING, CLOSED);
-      CLOSED.init(false, true, CLOSED, CLOSED, CLOSED, CLOSED, CLOSED, CLOSED);
-    }
-    
-    private boolean isOpen;
-    private boolean isActive;
-    private Lifecycle onActivate;
-    private Lifecycle onDeactivate;
-    private Lifecycle onConnect;
-    private Lifecycle onAbort;
-    private Lifecycle onClose;
-    private Lifecycle onClosed;
-    
-    private void init(boolean io, boolean ia, Lifecycle ac, Lifecycle da, Lifecycle cn, Lifecycle ab, Lifecycle cl, Lifecycle cd) {
-      isOpen = io;
-      isActive = ia;
-      onActivate = ac;
-      onDeactivate = da;
-      onConnect = cn;
-      onAbort = ab;
-      onClose = cl;
-      onClosed = cd;
-    }
-    public boolean isOpen() {
-      return isOpen;
-    }
-    
-    public boolean isActive() {
-      return isActive;
-    }
-    
-    public Lifecycle activate() {
-      return onActivate;
-    }
-    
-    public Lifecycle deactivate() {
-      return onDeactivate;
-    }
-    
-    public Lifecycle connect() {
-      return onConnect;
-    }
-    
-    public Lifecycle abort() {
-      return onAbort;
-    }
-    
-    public Lifecycle close() {
-      return onClose;
-    }
-    
-    public Lifecycle closed() {
-      return onClosed;
-    }
-  
-  }
-
-  /**
-   * Specifiers for how much effort to put into validating a {@link Connection}.
-   * The amount of effort put into checking should be non-decreasing from NONE
-   * (least effort) to COMPLETE (most effort). Exactly what is checked is
-   * implementation dependent. For example, a memory resident database driver
-   * might implement SOCKET and NETWORK to be the same as LOCAL. SERVER might
-   * verify that a database manager thread is running and COMPLETE might trigger
-   * the database manager thread to run a deadlock detection algorithm.
-   */
-  public enum Validation {
-    /**
-     * isValid fails only if the {@link Connection} is closed.
-     */
-    NONE,
-    /**
-     * {@link NONE} plus check local resources
-     */
-    LOCAL,
-    /**
-     * {@link LOCAL} plus the server isn't obviously unreachable (dead socket)
-     */
-    SOCKET,
-    /**
-     * {@link SOCKET} plus the network is intact (network PING)
-     */
-    NETWORK,
-    /**
-     * {@link NETWORK} plus significant server processes are running
-     */
-    SERVER,
-    /**
-     * everything that can be checked is working. At least {@link SERVER}.
-     */
-    COMPLETE;
-  }
-
-  /**
-   * A Listener that is notified of changes in a Connection's lifecycle.
-   */
-  public interface ConnectionLifecycleListener extends java.util.EventListener {
-
-    /**
-     * If this {@link java.util.EventListener} is registered with a
-     * {@link Connection} this method is called whenever that
-     * {@link Connection}'s lifecycle changes. Note that the lifecycle may have
-     * changed again by the time this method is called so the
-     * {@link Connection}'s current lifecycle may be different from the value of
-     * {@code current}.
-     *
-     * @param conn the {@link Connection}
-     * @param previous the previous value of the lifecycle
-     * @param current the new value of the lifecycle
-     */
-    public void lifecycleEvent(Connection conn, Lifecycle previous, Lifecycle current);
-  }
-
-  /**
-   * A {@link Connection} builder. A {@link Connection} is initially in the
-   * {@link Connection.Lifecycle#NEW} lifecycle state. It transitions to the
-   * {@link Connection.Lifecycle#OPEN} lifecycle state when fully initialized or
-   * to {@link Connection.Lifecycle#CLOSED} if initialization fails.
-   *
-   */
-  public interface Builder {
-
-    /**
-     * Specify a property and its value for the built {@link Connection}.
-     *
-     * @param p {@link ConnectionProperty} to set. Not {@code null}.
-     * @param v value for the property
-     * @return this {@link Builder}
-     * @throws IllegalArgumentException if {@code p.validate(v)} does not return
-     * true, if this method has already been called with the property
-     * {@code p}, or the implementation does not support the {@link ConnectionProperty}.
-     */
-    public Builder property(ConnectionProperty p, Object v);
-
-    /**
-     * 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}.
-     *
-     * @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();
-  }
-
-  /**
-   * Returns an {@link Operation} that connects this {@link Connection} to a
-   * server. If the Operation completes successfully and the lifecycle is
-   * {@link Lifecycle#NEW} -&gt; {@link Lifecycle#OPEN}. If lifecycle is
-   * {@link Lifecycle#NEW_INACTIVE} -&gt; {@link Lifecycle#INACTIVE}. If the
-   * {@link Operation} completes exceptionally the lifecycle -&gt;
-   * {@link Lifecycle#CLOSED}. The lifecycle must be {@link Lifecycle#NEW} or
-   * {@link Lifecycle#NEW_INACTIVE} when the {@link Operation} is executed.
-   * Otherwise the {@link Operation} will complete exceptionally with
-   * {@link SqlException}.
-   *
-   * Note: It is highly recommended to use the {@link connect()} convenience
-   * method or to use {@link DataSource#getConnection} which itself calls
-   * {@link connect()}. Unless there is a specific need, do not call this method
-   * directly.
-   *
-   * This method exists partially to clearly explain that while creating a
-   * {@link Connection} is non-blocking, the act of connecting to the server may
-   * block and so is executed asynchronously. We could write a bunch of text
-   * saying this but defining this method is more explicit. Given the
-   * {@link connect()} convenience methods there's probably not much reason to
-   * use this method, but on the other hand, who knows, so here it is.
-   *
-   * @return an {@link Operation} that connects this {@link Connection} to a
-   * server.
-   * @throws IllegalStateException if this {@link Connection} is in a lifecycle
-   * state other than {@link Lifecycle#NEW}.
-   */
-  public Operation<Void> connectOperation();
-
-  /**
-   * Convenience method that supports the fluent style of the builder needed by
-   * try with resources.
-   *
-   * Note: A {@link Connection} is an {@link OperationGroup} and so has some
-   * advanced features that most users do not need. Management of these features
-   * is encapsulated in this method and the corresponding {@link close()}
-   * convenience method. The vast majority of users should just use these
-   * methods and not worry about the advanced features. The convenience methods
-   * do the right thing for the overwhelming majority of use cases. A tiny
-   * number of users might want to take advantage of the advanced features that
-   * {@link OperationGroup} brings to {@link Connection} and so would call
-   * {@link connectOperation} directly.
-   *
-   * @return this Connection
-   * @throws IllegalStateException if this {@link Connection} is in a lifecycle
-   * state other than {@link Lifecycle#NEW}.
-   */
-  public default Connection connect() {
-    this.submitHoldingForMoreMembers();
-    this.connectOperation()
-            .submit();
-    return this;
-  }
-
-  /**
-   * Convenience method that supports the fluent style of the builder needed by
-   * try with resources.
-   *
-   * @param onError an Exception handler that is called if the connect
-   * {@link Operation} completes exceptionally.
-   * @return this {@link Connection}
-   * @throws IllegalStateException if this {@link Connection} is in a lifecycle
-   * state other than {@link Lifecycle#NEW}.
-   */
-  public default Connection connect(Consumer<Throwable> onError) {
-    this.submitHoldingForMoreMembers();
-    this.connectOperation()
-            .submit()
-            .getCompletionStage()
-            .exceptionally(t -> { onError.accept(t); return null; } );
-    return this;
-  }
-
-  /**
-   * Returns an {@link Operation} that verifies that the resources are available
-   * and operational. Successful completion of that {@link Operation} implies
-   * that at some point between the beginning and end of the {@link Operation}
-   * the Connection was working properly to the extent specified by {@code depth}.
-   * There is no guarantee that the {@link Connection} is still working after 
-   * completion. If the {@link Connection} is not valid the Operation completes
-   * exceptionally.
-   *
-   * @param depth how completely to check that resources are available and
-   * operational. Not {@code null}.
-   * @return an {@link Operation} that will validate this {@link Connection}
-   * @throws IllegalStateException if this Connection is not active
-   */
-  public Operation<Void> validationOperation(Validation depth);
-
-  /**
-   * Convenience method to validate a {@link Connection}.
-   *
-   * @param depth how completely to check that resources are available and
-   * operational. Not {@code null}.
-   * @param minTime how long to wait. If 0, wait forever
-   * @param onError called if validation fails or times out. May be
-   * {@code null}.
-   * @return this {@link Connection}
-   * @throws IllegalArgumentException if {@code milliseconds} &lt; 0 or
-   * {@code depth} is {@code null}.
-   * @throws IllegalStateException if this Connection is not active
-   */
-  public default Connection validate(Validation depth,
-          Duration minTime,
-          Function<Throwable, Void> onError) {
-    this.validationOperation(depth)
-            .timeout(minTime)
-            .submit()
-            .getCompletionStage()
-            .exceptionally(onError);
-    return this;
-  }
-
-  /**
-   * Create an {@link Operation} to close this {@link Connection}. When the
-   * {@link Operation} is executed, if this {@link Connection} is open -&gt;
-   * {@link Lifecycle#CLOSING}. If this {@link Connection} is closed executing
-   * the returned {@link Operation} is a no-op. When the queue is empty and all
-   * resources released -&gt; {@link Lifecycle#CLOSED}.
-   *
-   * A close {@link Operation} is never skipped. Even when the
-   * {@link Connection} is dependent, the default, and an {@link Operation}
-   * completes exceptionally, a close {@link Operation} is still executed. If
-   * the {@link Connection} is parallel, a close {@link Operation} is not
-   * executed so long as there are other {@link Operation}s or the
-   * {@link Connection} is held; for more {@link Operation}s.
-   *
-   * Note: It is highly recommended to use try with resources or the
-   * {@link close()} convenience method. Unless there is a specific need, do not
-   * call this method directly.
-   *
-   * @return an {@link Operation} that will close this {@link Connection}.
-   * @throws IllegalStateException if the Connection is not active
-   */
-  public Operation<Void> closeOperation();
-
-  /**
-   * Create and submit an {@link Operation} to close this {@link Connection}.
-   * Convenience method.
-   *
-   * Note: A {@link Connection} is an {@link OperationGroup} and so has some
-   * advanced features; that most users do not need. Management of these
-   * features is encapsulated in this method and the corresponding
-   * {@link connect()} convenience method. The vast majority of users should
-   * just use these methods and not worry about the advanced features. The
-   * convenience methods do the right thing for the overwhelming majority of use
-   * cases. A tiny number of user might want to take advantage of the advanced
-   * features that {@link OperationGroup} brings to {@link Connection} and so
-   * would call {@link closeOperation} directly.
-   *
-   * @throws IllegalStateException if the Connection is not active
-   */
-  @Override
-  public default void close() {
-    this.closeOperation()
-            .submit();
-    this.releaseProhibitingMoreMembers();
-  }
-
-  /**
-   * Create a new {@link OperationGroup} for this {@link Connection}.
-   *
-   * @param <S> the result type of the member {@link Operation}s of the returned
-   * {@link OperationGroup}
-   * @param <T> the result type of the collected results of the member
-   * {@link Operation}s
-   * @return a new {@link OperationGroup}.
-   * @throws IllegalStateException if this Connection is not active
-   */
-  public <S, T> OperationGroup<S, T> operationGroup();
-
-  /**
-   * Returns a new {@link Transaction} that can be used as an argument to a
-   * commit Operation.
-   *
-   * It is most likely an error to call this within an error handler, or any
-   * handler as it is very likely that when the handler is executed the next
-   * submitted endTransaction {@link Operation} will have been created with a different
-   * Transaction.
-   * 
-   * ISSUE: Should this be moved to OperationGroup?
-   *
-   * @return a new {@link Transaction}. Not retained.
-   * @throws IllegalStateException if this Connection is not active
-   */
-  public Transaction transaction();
-  
-  /**
-   * Convenience method that submits an endTransaction {@link Operation}. This
-   * {@link Operation} will always attempt to commit the transaction. 
-   * When this method is used there is no way to cause the transaction to be ended
-   * with a rollback.
-   * 
-   * @return this {@link Connection}
-   */
-  public default CompletionStage<TransactionOutcome> commit() {
-    return this.commitMaybeRollback(transaction());
-  }
-  
-  /**
-   * Create an endTransaction {@link Operation}, set it to rollback only,
-   * 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();
-  }
-
-  /**
-   * Register a listener that will be called whenever there is a change in the
-   * lifecycle of this {@link Connection}.If the listener is already registered
- this is a no-op. ISSUE: Should lifecycleListener be a ConnectionProperty so that it is 
- always reestablished on Connection.activate?
-   *
-   * @param listener Not {@code null}.
-   * @return this Connection
-   * @throws IllegalStateException if this Connection is not active
-   */
-  public Connection registerLifecycleListener(ConnectionLifecycleListener listener);
-  
-  /**
-   * Removes a listener that was registered by calling
-   * registerLifecycleListener.Sometime after this method is called the listener
-   * will stop receiving lifecycle events. If the listener is not registered,
-   * this is a no-op.
-   *
-   * @param listener Not {@code null}.
-   * @return this Connection
-   * @throws IllegalStateException if this Connection is not active
-   */
-  public Connection deregisterLifecycleListener(ConnectionLifecycleListener listener);
-
-  /**
-   * Return the current lifecycle of this {@link Connection}. 
-   *
-   * @return the current lifecycle of this {@link Connection}.
-   */
-  public Lifecycle getConnectionLifecycle();
-
-  /**
-   * Terminate this {@link Connection}. If lifecycle is
-   * {@link Lifecycle#NEW}, {@link Lifecycle#OPEN}, {@link Lifecycle#INACTIVE}
-   * or {@link Lifecycle#CLOSING} -&gt; {@link Lifecycle#ABORTING} If lifecycle
-   * is {@link Lifecycle#ABORTING} or {@link Lifecycle#CLOSED} this is a no-op.
-   * If an {@link Operation} is currently executing, terminate it immediately.
-   * Remove all remaining {@link Operation}s from the queue. {@link Operation}s
-   * are not skipped. They are just removed from the queue.
-   *
-   * @return this {@link Connection}
-   */
-  public Connection abort();
-
-  /**
-   * Return the set of properties configured on this {@link Connection}
-   * excepting any sensitive properties. Neither the key nor the value for
-   * sensitive properties are included in the result. Properties (other than
-   * sensitive properties) that have default values are included even when not
-   * explicitly set. Properties that have no default value and are not set
-   * explicitly are not included.
-   *
-   * @return a {@link Map} of property, value. Not modifiable. May be retained.
-   * Not {@code null}.
-   * @throws IllegalStateException if this Connection is not active
-   */
-  public Map<ConnectionProperty, Object> getProperties();
-  
-  /**
-   *
-   * @return a {@link ShardingKey.Builder} for this {@link Connection}
-   * @throws IllegalStateException if this Connection is not active
-   */
-  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}
-   * -&gt; {@link Lifecycle#OPEN}. If the lifecycle is
-   * {@link Lifecycle#NEW_INACTIVE} -&gt; {@link Lifecycle#NEW}.
-   *
-   * @return this {@link Connection}
-   * @throws IllegalStateException if this {@link Connection} is closed.
-   */
-  public Connection activate();
-
-  /**
-   * Makes this {@link Connection} inactive. After a call to this method
-   * previously submitted Operations will be executed normally. If the lifecycle
-   * is {@link Lifecycle#NEW} -&gt; {@link Lifecycle#NEW_INACTIVE}. if the
-   * lifecycle is {@link Lifecycle#OPEN} -&gt; {@link Lifecycle#INACTIVE}. If
-   * the lifecycle is {@link Lifecycle#INACTIVE} or
-   * {@link Lifecycle#NEW_INACTIVE} this method is a no-op. After calling this
-   * method or calling any method other than {@link deactivate}, {@link activate},
-   * {@link abort}, or {@link getConnectionLifecycle} will throw
-   * {@link IllegalStateException}. Local {@link Connection} state not created
-   * by {@link Connection.Builder} may not be preserved.
-     * 
-   * Any implementation of a {@link Connection} pool is by default required to
-   * call {@code deactivate} when putting a {@link Connection} into a pool. The
-   * implementation is required to call {@code activate} when removing a
-   * {@link Connection} from a pool so the {@link Connection} can be used. An
-   * implementation of a {@link Connection} pool may have an optional mode where
-   * it does not call {@code deactivate}/{@code activate} as required above. The
-   * behavior of the pool and {@link Connection}s cached in the pool in such a
-   * mode is entirely implementation dependent.
-   *
-   * @return this {@link Connection}
-   * @throws IllegalStateException if this {@link Connection} is closed
-   */
-  public Connection deactivate();
-  
-}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ConnectionProperty.java	Fri Jul 06 20:37:32 2018 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +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;
-
-/**
- * An attribute of a {@link Connection} that can be configured to influence its
- * behavior. Implementors of this interface define the properties of
- * {@link Connection}s. The {@link Connection.Builder#property} method is used to set the values
- * of {@link Connection} properties.
- * 
- * Implementations must be thread safe.
- * 
- */
-public interface ConnectionProperty {
-
-  /**
-   * Return the name of this {@link ConnectionProperty}.
-   * 
-   * @return the name of this {@link ConnectionProperty}
-   */
-  public String name();
-
-  /**
-   * Return the type of the value of this {@link ConnectionProperty}. Any value
-   * set for this property must be assignable to this type.
-   *
-   * @return the type of the values of this {@link ConnectionProperty}
-   */
-  public Class<?> range();
-
-  /**
-   * Determine whether a value is valid for this {@link ConnectionProperty}. Returns
-   * {@code true} if {@code value} is valid and {@code false} otherwise.
-   * 
-   * @param value a value for this {@link ConnectionProperty}
-   * @return {@code true} iff {@code value} is valid for this {@link ConnectionProperty}
-   */
-  public default boolean validate(Object value) {
-    return (value == null && this.range() == Void.class) || this.range().isInstance(value);
-  }
-
-  /**
-   * Return the value for this property to use if no other value is set. For
-   * this to have any meaning for a user defined property the property must be
-   * registered with the {@link DataSource} by calling 
-   * {@link DataSource.Builder#registerConnectionProperty}. 
-   *
-   * @return the default value or {@code null} if there is no default value
-   */
-  public Object defaultValue();
-
-  /**
-   * Returns true if this {@link ConnectionProperty} is contains sensitive information
-   * such as a password or encryption key.
-   *
-   * @return true iff this is sensitive
-   */
-  public boolean isSensitive();
-
-  /**
-   * Returns an {@link Operation} that will configure the {@link Connection} to have the
-   * specified property value.May return {@code null} if no {@link Operation} needed. The
- returned {@link Operation} is a member of group but is not submitted.
-   *
-   * Called by {@link Connection.Builder#build()} to configure a {@link Connection} as specified
-   * in the {@link Connection.Builder#property} method. ConnectionProperties known to the implementation
-   * may return {@code null} and rely on the implementation to do the right thing.
-   *
-   * @param <S>
-   * @param group an {@link OperationGroup} which will be the container of the returned
-   * {@link Operation}, if any
-   * @param value the value to which the property is to be set. May be null if
-   * {@link range()} is {@link Void}.
-   * @return an {@link Operation} or null
-   * @throws IllegalStateException if it is not possible to configure the
-   * {@link Connection} as specified.
-   * @throws IllegalArgumentException if {@code this.validate(value)} returns {@code false}
-   */
-  public default <S> Operation<? extends S> configureOperation(OperationGroup<S, ?> group, Object value) {
-    if (validate(value)) {
-      return null;
-    }
-    else {
-      throw new IllegalArgumentException(value.toString() + " is invalid");
-    }
-  }
-
-}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSource.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSource.java	Mon Jul 09 15:09:06 2018 -0400
@@ -28,9 +28,10 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.LongConsumer;
 
 /**
- * Uses the builder pattern to get a {@link Connection}. A {@link DataSource#getConnection}
+ * Uses the builder pattern to get a {@link Session}. A {@link DataSource#getSession}
  * method is provided as a convenience.
  * 
  * Implementations must be thread safe.
@@ -48,74 +49,87 @@
   public interface Builder {
 
     /**
-     * A convenience method for setting the {@link AdbaConnectionProperty#URL}.
+     * Specify a property and its value for the built {@link DataSource}.
      *
-     * @param url the value to be set for {@link AdbaConnectionProperty#URL}
+     * @param p {@link DataSourceProperty} to set. Not {@code null}.
+     * @param v value for the property
      * @return this {@link Builder}
-     * @see connectionProperty
+     * @throws IllegalArgumentException if {@code p.validate(v)} does not return
+     * true, if this method has already been called with the property
+     * {@code p}, or the implementation does not support the 
+     * {@link DataSourceProperty}.
+     */
+    public Builder property(DataSourceProperty p, Object v);
+
+    /**
+     * A convenience method for setting the {@link AdbaSessionProperty#URL}.
+     *
+     * @param url the value to be set for {@link AdbaSessionProperty#URL}
+     * @return this {@link Builder}
+     * @see sessionProperty
      */
     public default Builder url(String url) {
-      return connectionProperty(AdbaConnectionProperty.URL, url);
+      return sessionProperty(AdbaSessionProperty.URL, url);
     }
 
     /**
-     * A convenience method for setting the {@link AdbaConnectionProperty#USER}.
+     * A convenience method for setting the {@link AdbaSessionProperty#USER}.
      *
-     * @param name the value to be set for {@link AdbaConnectionProperty#USER}
+     * @param name the value to be set for {@link AdbaSessionProperty#USER}
      * @return this {@link Builder}
-     * @see connectionProperty
+     * @see sessionProperty
      */
     public default Builder username(String name) {
-      return connectionProperty(AdbaConnectionProperty.USER, name);
+      return sessionProperty(AdbaSessionProperty.USER, name);
     }
 
     /**
-     * A convenience method for setting the {@link AdbaConnectionProperty#PASSWORD}.
+     * A convenience method for setting the {@link AdbaSessionProperty#PASSWORD}.
      *
-     * @param password the value to be set for {@link AdbaConnectionProperty#PASSWORD}
+     * @param password the value to be set for {@link AdbaSessionProperty#PASSWORD}
      * @return this {@link Builder}
-     * @see connectionProperty
+     * @see sessionProperty
      */
     public default Builder password(String password) {
-      return connectionProperty(AdbaConnectionProperty.PASSWORD, password);
+      return sessionProperty(AdbaSessionProperty.PASSWORD, password);
     }
     
     /**
-     * Specify the value of a {@link Connection} property that will be set by default on
-     * all {@link Connection}s produced by this {@link DataSource}. A different value can be set
-     * for a particular {@link Connection} via {@link Connection.Builder#property}.
+     * Specify the value of a {@link Session} property that will be set by default on
+     * all {@link Session}s produced by this {@link DataSource}. A different value can be set
+     * for a particular {@link Session} via {@link Session.Builder#property}.
      *
-     * @param property the {@link ConnectionProperty} to be set. May not be {@code null}.
+     * @param property the {@link SessionProperty} to be set. May not be {@code null}.
      * @param value the value to be set for {@code property}
      * @return this {@link Builder}
      * @throws IllegalArgumentException if {@code property.validate(value)} does not
      * return {@code true}. If it throws an {@link Exception} that {@link Exception} is the cause. Or if
      * this property has been specified previously to this method or
-     * {@link connectionProperty} or {@link registerConnectionProperty}.
+     * {@link sessionProperty} or {@link registerSessionProperty}.
      * @throws IllegalStateException if {@link build} has previously been called.
      */
-    public Builder defaultConnectionProperty(ConnectionProperty property, Object value);
+    public Builder defaultSessionProperty(SessionProperty property, Object value);
 
     /**
-     * Specify the value of a {@link Connection} property that will be set on
-     * all {@link Connection}s produced by the built {@link DataSource}.
+     * Specify the value of a {@link Session} property that will be set on
+     * all {@link Session}s produced by the built {@link DataSource}.
      * Attempting to set a different value via
-     * {@link Connection.Builder#property} will throw
+     * {@link Session.Builder#property} will throw
      * {@link IllegalArgumentException}.
      *
-     * @param property the {@link ConnectionProperty} to set. May not be
+     * @param property the {@link SessionProperty} to set. May not be
      * {@code null}.
      * @param value the value to set as the default for {@code property}
      * @return this {@link Builder}
      * @throws IllegalArgumentException if {@code property.validate(value)} does
      * not return {@code true}. If it throws an {@link Exception} that
      * {@link Exception} is the cause. Or if this property has been specified
-     * previously to this method or {@link defaultConnectionProperty} or
-     * {@link registerConnectionProperty}.
+     * previously to this method or {@link defaultSessionProperty} or
+     * {@link registerSessionProperty}.
      * @throws IllegalStateException if {@link build} has previously been
      * called.
      */
-    public Builder connectionProperty(ConnectionProperty property, Object value);
+    public Builder sessionProperty(SessionProperty property, Object value);
 
     /**
      * Make a user defined property known to the implementation. One reason to
@@ -123,46 +137,47 @@
      * {@link DataSource} doesn't know about the property then it cannot know to
      * set the default value. Convenience method.
      *
-     * @param property the {@link ConnectionProperty} to make known. May not be
+     * @param property the {@link SessionProperty} to make known. May not be
      * {@code null}.
      * @return this Builder
      * @throws IllegalArgumentException if this property has been specified
-     * previously to this method or {@link connectionProperty} or
-     * {@link defaultConnectionProperty}.
+     * previously to this method or {@link sessionProperty} or
+     * {@link defaultSessionProperty}.
      * @throws IllegalStateException if {@link build} has previously been
      * called.
      */
-    public default Builder registerConnectionProperty(ConnectionProperty property) {
-      return defaultConnectionProperty(property, property.defaultValue());
+    public default Builder registerSessionProperty(SessionProperty property) {
+      return defaultSessionProperty(property, property.defaultValue());
     }
 
     /**
      * Provide a method that the built {@link DataSource} will call to control the
-     * rate of {@link DataSource#connectOperation} submissions. The built
+     * rate of {@link Session} creations. 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
+     * when the {@link DataSource} is able to accept more calls to
+     * {@link DataSource#builder}. 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 
+     * {@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>
+     * Since the user thread is never blocked, a user thread could in theory 
+     * create, attach, use, and close {@link Session}s faster than the underlying
+     * implementation can process the submitted work. At some point work would
+     * start timing out or Java would run out of memory to store the queued
+     * {@link Operation}s. This is a poor way address the issue. This method 
+     * allows user code to get feedback from the {@link DataSource} as to whether
+     * the {@link DataSource} can accept more work.
+     * </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);
+    public Builder requestHook(LongConsumer request);
 
     /**
      * Return a DataSource configured as specified. 
@@ -175,43 +190,43 @@
   }
 
   /**
-   * Returns a {@link Connection} builder. By default that builder will return
-   * {@link Connection}s with the {@code ConnectionProperty}s specified when creating this
-   * DataSource. Default and unspecified {@link ConnectionProperty}s can be set with
+   * Returns a {@link Session} builder. By default that builder will return
+   * {@link Session}s with the {@code SessionProperty}s specified when creating this
+   * DataSource. Default and unspecified {@link SessionProperty}s can be set with
    * the returned builder.
    *
-   * @return a new {@link Connection} builder. Not {@code null}.
+   * @return a new {@link Session} builder. Not {@code null}.
    * @throws IllegalStateException if this {@link DataSource} is closed
    */
-  public Connection.Builder builder();
+  public Session.Builder builder();
 
   /**
-   * Returns a {@link Connection} that has a submitted connect {@link Operation}. Convenience
+   * Returns a {@link Session} that has a submitted attach {@link Operation}. Convenience
    * method for use with try with resources.
    *
-   * @return a {@link Connection}
+   * @return a {@link Session}
    * @throws IllegalStateException if this {@link DataSource} is closed
    */
-  public default Connection getConnection() {
-    return builder().build().connect();
+  public default Session getSession() {
+    return builder().build().attach();
   }
 
   /**
-   * Returns a {@link Connection} that has a submitted connect {@link Operation} with an error
+   * Returns a {@link Session} that has a submitted attach {@link Operation} with an error
    * handler. Convenience method for use with try with resources. The error
-   * handle handles errors in the connect {@link Operation}.
+   * handle handles errors in the attach {@link Operation}.
    *
-   * @param handler for errors in the connect {@link Operation}
-   * @return a {@link Connection}
+   * @param handler for errors in the attach {@link Operation}
+   * @return a {@link Session}
    * @throws IllegalStateException if this {@link DataSource} is closed
    */
-  public default Connection getConnection(Consumer<Throwable> handler) {
-    return builder().build().connect(handler);
+  public default Session getSession(Consumer<Throwable> handler) {
+    return builder().build().attach(handler);
   }
   
   /**
    * Translates a SQL string from the format specified by the format argument
-   * to a format that can be used to create {@link Operation}s for the {@link Connection}s
+   * to a format that can be used to create {@link Operation}s for the {@link Session}s
    * provided by this {@link DataSource}. 
    * 
    * ISSUE: Just an idea
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSourceFactory.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSourceFactory.java	Mon Jul 09 15:09:06 2018 -0400
@@ -63,5 +63,5 @@
    * @return a {@link DataSource} builder. Not {@code null}.
    */
   public DataSource.Builder builder();
-
+  
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/DataSourceProperty.java	Mon Jul 09 15:09:06 2018 -0400
@@ -0,0 +1,95 @@
+/*
+ * 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;
+
+/**
+ * An attribute of a {@link DataSource} that can be configured to influence its
+ * behavior. Implementors of this interface define the properties of
+ * {@link DataSource}s. The {@link DataSource.Builder#property} method is used
+ * to set the values of {@link DataSource} properties.
+ *
+ * Implementations must be thread safe.
+ *
+ */
+public interface DataSourceProperty {
+
+  /**
+   * Return the name of this {@link DataSourceProperty}.
+   *
+   * @return the name of this {@link DataSourceProperty}
+   */
+  public String name();
+
+  /**
+   * Return the type of the value of this {@link DataSourceProperty}. Any value
+   * set for this property must be assignable to this type.
+   *
+   * @return the type of the values of this {@link DataSourceProperty}
+   */
+  public Class<?> range();
+
+  /**
+   * Determine whether a value is valid for this {@link DataSourceProperty}.
+   * Returns {@code true} if {@code value} is valid and {@code false} otherwise.
+   *
+   * @param value a value for this {@link DataSourceProperty}
+   * @return {@code true} iff {@code value} is valid for this
+   * {@link DataSourceProperty}
+   */
+  public default boolean validate(Object value) {
+    return (value == null && this.range() == Void.class) || this.range().isInstance(value);
+  }
+
+  /**
+   * Return the value for this property to use if no other value is set. This
+   * has no meaning for user defined properties as the implementation is not
+   * aware of the the existence of the property. Default values are used for
+   * standard and implementation defined properties.
+   *
+   * @return the default value or {@code null} if there is no default value
+   */
+  public Object defaultValue();
+
+  /**
+   * Returns true if this {@link DataSourceProperty} is contains sensitive
+   * information such as a password or encryption key.
+   *
+   * @return true iff this is sensitive
+   */
+  public boolean isSensitive();
+
+  /**
+   * Configure the {@link DataSource as appropriate for the given {@code value} 
+   * of this {@link DataSourceProperty}. This is primarily for the use of user 
+   * defined properties.
+   *
+   * @param ds the {@link DataSource} to configure
+   * @param value the value of this property
+   */
+  public default void configure(DataSource ds, Object value) {
+    // nothing
+  }
+  
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Examples.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Examples.java	Mon Jul 09 15:09:06 2018 -0400
@@ -1,5 +1,3 @@
-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.
@@ -25,6 +23,8 @@
  * questions.
  */
 
+package jdk.incubator.sql2;
+
 import java.io.DataInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -44,7 +44,7 @@
   
   // DataSourceFactory
 
-  public DataSource getDataSource(String url, String user, String pass) {
+  public DataSource getDataSource() {
     return DataSourceFactory.newFactory("oracle.database.adba")
             .builder()
             .url("//host.oracle.com:5521/example")
@@ -56,8 +56,8 @@
   // RowCountOperation
   
   public void insertItem(DataSource ds, Item item) {
-    try (Connection conn = ds.getConnection()) {
-      conn.rowCountOperation("insert into tab values (:id, :name, :answer)")
+    try (Session session = ds.getSession()) {
+      session.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)
@@ -68,8 +68,8 @@
   // 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")
+    try (Session session = ds.getSession()) {
+      session.<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)) )
@@ -80,8 +80,8 @@
   // 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")
+    try (Session session = ds.getSession()) {
+      return session.<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),
@@ -97,8 +97,8 @@
 
   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()
+    try (Session session = ds.getSession()) {
+      OperationGroup group = session.operationGroup()
               .independent();
       for (Item elem : list) {
         group.rowCountOperation(sql)
@@ -113,6 +113,7 @@
                 });
       }
       group.submit();
+      
     }
   }
   
@@ -120,8 +121,8 @@
   
   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()
+    try (Session session = ds.getSession()) {
+      OperationGroup group = session.operationGroup()
               .independent();
       group.submitHoldingForMoreMembers();
       for (Item elem : list) {
@@ -143,8 +144,8 @@
   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()
+    try (Session session = ds.getSession()) {
+      OperationGroup<Object, Object> group = session.operationGroup()
               .independent()
               .parallel();
       group.submitHoldingForMoreMembers();
@@ -172,12 +173,12 @@
     }
   }
   
-  // Transaction
+  // TransactionEnd
   
   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")
+    try (Session session = ds.getSession(t -> System.out.println("ERROR: " + t.toString()))) {
+      TransactionEnd trans = session.transactionEnd();
+      CompletionStage<Integer> idPromise = session.<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), 
@@ -186,7 +187,7 @@
               .onError( t -> trans.setRollbackOnly() )
               .submit()
               .getCompletionStage();
-      conn.<Long>rowCountOperation("update emp set deptno = :1 where empno = :2")
+      session.<Long>rowCountOperation("update emp set deptno = :1 where empno = :2")
               .set("1", 50, AdbaType.INTEGER)
               .set("2", idPromise, AdbaType.INTEGER)
               .apply(c -> { 
@@ -200,8 +201,8 @@
               .submit();
           //    .getCompletionStage()
           //    .exceptionally( t -> { trans.setRollbackOnly(); return null; } ) // incorrect
-      conn.catchErrors();
-      conn.commitMaybeRollback(trans);
+      session.catchErrors();
+      session.commitMaybeRollback(trans);
     }    
   }
   
@@ -246,8 +247,8 @@
 
     };
     
-    try (Connection conn = ds.getConnection()) {
-      return conn.<List<String>>rowPublisherOperation(sql)
+    try (Session session = ds.getSession()) {
+      return session.<List<String>>rowPublisherOperation(sql)
               .subscribe(subscriber, result)
               .submit()
               .getCompletionStage();
@@ -258,13 +259,13 @@
     
   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()
+    try (Session session = ds.getSession()) {
+      OperationGroup<Long, Long> group = session.<Long, Long>operationGroup()
               .independent()
               .collect(Collectors.summingLong(c -> c));
       group.submitHoldingForMoreMembers();
       Semaphore demand = new Semaphore(0);
-      conn.requestHook( n -> demand.release(n.intValue()) );
+      session.requestHook( n -> demand.release((int)n) );
       while (in.available() > 0) {
         demand.acquire(1); // user thread blocked by Semaphore, not by ADBA
         group.<Long>rowCountOperation(insert)
@@ -287,8 +288,8 @@
                                            List<String> names, 
                                            List<Integer> answers) {
     String sql = "insert into tab values (?, ?, ?)";
-    try (Connection conn = ds.getConnection()) {
-      return conn.<Long>arrayRowCountOperation(sql)
+    try (Session session = ds.getSession()) {
+      return session.<Long>arrayRowCountOperation(sql)
           .collect(Collectors.summingLong( c -> c.getCount() ))
           .set("1",ids, AdbaType.INTEGER)
           .set("2", names, AdbaType.VARCHAR)
@@ -302,8 +303,8 @@
   
   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)
+    try (Session session = ds.getSession()) {
+      return session.<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)
@@ -317,8 +318,8 @@
   
   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)
+    try (Session session = ds.getSession()) {
+      return session.<Item>outOperation(sql)
               .set("id", id, AdbaType.INTEGER)
               .outParameter("name", AdbaType.VARCHAR)
               .outParameter("answer", AdbaType.INTEGER)
@@ -334,7 +335,7 @@
   
   // LocalOperation
   
-  // ConnectionProperty
+  // SessionProperty
   
   // Sharding
   
@@ -342,7 +343,36 @@
   
   // Column navigation
   
+  private class Name { Name(String ... args) {} }
+  private class Address { Address(String ... args) {} }
+  
+  private Name getName(Result.Column col) {
+    return new Name(
+      col.get(String.class), // title
+      col.next().get(String.class), // given name
+      col.next().get(String.class), // middle initial
+      col.next().get(String.class), // family name
+      col.next().get(String.class)); // suffix
+  }
+  
+  private Address getAddress(Result.Column col) {
+    List<String> a = new ArrayList<>();
+    for (Result.Column c : col.slice(6)) {
+      a.add(c.get(String.class));
+    }
+    return new Address(a.toArray(new String[0]));
+  }
+  public void columNavigation(Result.RowColumn column) {
+    Name fullName = getName(column.at("name_title"));
+    Address streetAddress = getAddress(column.at("street_address_line1"));
+    Address mailingAddress = getAddress(column.at("mailing_address_line1"));
+    for (Result.Column c : column.at(-14)) { // dump the last 14 columns
+      System.out.println("trailing column " + c.get(String.class));
+    }
+  }
+  
   // Error handling
+
   
   static public class Item {
     public int id;
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/LocalOperation.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/LocalOperation.java	Mon Jul 09 15:09:06 2018 -0400
@@ -33,7 +33,7 @@
  * not perform any database action. The result of a {@link LocalOperation} is
  * the result of calling the {@link Callable}. This type allows user code to
  * execute arbitrary code at particular points in the sequence of
- * {@link Operation}s executed by a {@link Connection} without having to execute
+ * {@link Operation}s executed by a {@link Session} without having to execute
  * a specific database action at the same time.
  *
  * @param <T> the type of the result of this {@link Operation}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java	Mon Jul 09 15:09:06 2018 -0400
@@ -119,7 +119,7 @@
    * member {@link Operation}s are executed strictly in the order they are
    * submitted.
    *
-   * Note: There is no covariant override of this method in {@link Connection}
+   * Note: There is no covariant override of this method in {@link Session}
    * as there is only a small likelihood of needing it.
    *
    * @return this {@link OperationGroup}
@@ -142,7 +142,7 @@
    * The result of this {@link OperationGroup}'s execution is the result of collecting the
    * results of the member {@link Operation}s that complete normally. 
    *
-   * Note: There is no covariant override of this method in {@link Connection}
+   * Note: There is no covariant override of this method in {@link Session}
    * as there is only a small likelihood of needing it.
    *
    * @return this {@link OperationGroup}
@@ -162,7 +162,7 @@
    * After all member {@link Operation}s have been removed from the queue this
    * {@link OperationGroup} is completed with {@code null}.
    *
-   * Note: There is no covariant override of this method in Connection as there
+   * Note: There is no covariant override of this method in Session as there
    * is only a small likelihood of needing it.
    *
    * ISSUE: Should the member Operations be skipped or otherwise completed
@@ -189,7 +189,7 @@
    * completes exceptionally and its queue is empty the {@link OperationGroup}
    * is completed.
    *
-   * Note: There is no covariant override of this method in Connection as there
+   * Note: There is no covariant override of this method in Session as there
    * is only a small likelihood of needing it.
    *
    * ISSUE: Need a better name.
@@ -208,7 +208,7 @@
    * queue this {@link OperationGroup} will be completed and removed from the
    * queue.
    *
-   * Note: There is no covariant override of this method in Connection as there
+   * Note: There is no covariant override of this method in Session as there
    * is only a small likelihood of needing it.
    *
    * ISSUE: Need a better name.
@@ -277,7 +277,7 @@
    * Usage Note: Frequently use of this method will require a type witness to
    * enable correct type inferencing.
    * <pre><code>
-   *   conn.<b>&lt;List&lt;Integer&gt;&gt;</b>arrayCountOperation(sql)
+   *   session.<b>&lt;List&lt;Integer&gt;&gt;</b>arrayCountOperation(sql)
    *     .set ...
    *     .collect ...
    *     .submit ...
@@ -391,27 +391,28 @@
    * The type argument {@link S} of the containing {@link OperationGroup} must
    * be a supertype of {@link TransactionOutcome}.
    *
-   * @param trans the Transaction that determines whether the Operation does a
+   * @param trans the TransactionEnd that determines whether the Operation does a 
    * database commit or a database rollback.
    * @return an {@link Operation} that will end the database transaction.
    * @throws IllegalStateException if this {@link OperationGroup} has been
    * submitted and is not held or is parallel.
    */
-  public Operation<TransactionOutcome> endTransactionOperation(Transaction trans);
+  public Operation<TransactionOutcome> endTransactionOperation(TransactionEnd trans);
 
   /**
    * 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}. The endTransaction Operation
+   * calling {@link TransactionEnd#setRollbackOnly}. The endTransaction Operation
    * is never skipped.
    *
-   * @param trans the Transaction that determines whether the {@link Operation} is a
+   * @param trans the TransactionEnd that determines whether the {@link Operation} is a
    * database commit or a database rollback.
-   * @return this {@link OperationGroup}
+   * @return a {@link CompletionStage} that is completed with the outcome of the 
+   * transaction
    * @throws IllegalStateException if this {@link OperationGroup} has been
    * submitted and is not held or is parallel.
    */
-  public default CompletionStage<TransactionOutcome> commitMaybeRollback(Transaction trans) {
+  public default CompletionStage<TransactionOutcome> commitMaybeRollback(TransactionEnd trans) {
     catchErrors();
     return this.endTransactionOperation(trans).submit().getCompletionStage();
   }
@@ -466,4 +467,5 @@
 
   @Override
   public OperationGroup<S, T> onError(Consumer<Throwable> handler);
+  
 }
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedOperation.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ParameterizedOperation.java	Mon Jul 09 15:09:06 2018 -0400
@@ -37,7 +37,7 @@
  * parameter id be the decimal integer representation of the parameter number.
  * 
  * A SQL structured type passed as an argument to a set method must be created
- * by the same {@link Connection} that the created the
+ * by the same {@link Session} that the created the
  * {@link ParameterizedOperation}. If not {@link IllegalArgumentException} is
  * thrown. A SQL structured type is one of
  * {@link SqlArray}, {@link SqlBlob}, {@link SqlClob}, {@link SqlRef} or
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/PrimitiveOperation.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/PrimitiveOperation.java	Mon Jul 09 15:09:06 2018 -0400
@@ -42,7 +42,7 @@
 
   /**
    * Add this {@link PrimitiveOperation} to the tail of the {@link Operation}
-   * collection of the {@link Connection} that created this
+   * collection of the {@link Session} that created this
    * {@link PrimitiveOperation}. A {@link PrimitiveOperation} can be submitted
    * only once. Once a {@link PrimitiveOperation} is submitted it is immutable.
    * Any attempt to modify a submitted {@link PrimitiveOperation} will throw
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java	Mon Jul 09 15:09:06 2018 -0400
@@ -241,12 +241,14 @@
     public default void forEach(Consumer<? super Column> action) {
       do {
         action.accept(this);
-      } while (hasNext());
+        if (!hasNext()) break;
+        next();
+      } while (true);
     }
 
     @Override
     public default Column iterator() {
-      return this;
+      return this.clone();
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Session.java	Mon Jul 09 15:09:06 2018 -0400
@@ -0,0 +1,618 @@
+/*
+ * 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.Map;
+import java.util.concurrent.CompletionStage;
+import java.util.function.Consumer;
+import java.util.function.LongConsumer;
+
+/**
+ * A {@link Session} is an abstraction of a SQL database and
+ * a group of {@link Operation}s to be executed by that SQL database. No method
+ * on {@link Session} or any of its dependent objects ({@link RowOperation}
+ * etc) blocks. Any method that might block must execute any potentially blocking
+ * action in a thread other than the calling thread.
+ * 
+ * <p>
+ * A {@link Session} is independent of any particular data source. Any data 
+ * source that meets the specifications set by the {@link Session.Builder} can
+ * be used to execute the {@link Operation}s submitted to the {@link Session].
+ * An application is expected to create, use, and close {@link Session}s as 
+ * needed. An application should hold a {@link Session} only when required by
+ * data source semantics. An implementation should cache and reused data source
+ * resources as appropriate. {@link Session}s should not be cached.
+ *
+ * <p>
+ * An implementation of this type must be thread safe as result and error
+ * handlers running asynchronously may be accessing a {@link Session} in
+ * parallel with each other and with a user thread. {@link Session}s are not
+ * required to support multiplexed use; a single {@link Session} should be
+ * used for only one unit of work at a time. Executing independent units of work
+ * on a single {@link Session} in parallel will most likely lead to
+ * unpredictable outcomes. As a rule of thumb only one user thread should access
+ * a {@link Session} at a time. Such a user thread should execute a complete
+ * unit of work before another user thread accesses the {@link Session}. An
+ * implementation may support parallel multiplexed use, but it is not required.</p>
+ *
+ * <p>
+ * All methods inherited from OperationGroup throw IllegalStateException if the
+ * the {@link Session} is not active.</p>
+ */
+public interface Session extends AutoCloseable, OperationGroup<Object, Object> {
+
+  /**
+   * Identifies the operational state of a {@link Session}.
+   */
+  public enum Lifecycle {
+    /**
+     * unattached. When a attach {@link Operation} is completed successfully
+     * -&gt; {@link OPEN}. If {@link deactivate} is called -&gt;
+     * {@link NEW_INACTIVE}. If {@link abort} is called -&gt; {@link ABORTING}.
+     * No {@link Operation}s other than attach and close will be performed. A
+ Session in this state is both 'open' and 'active'.
+     */
+    NEW,
+    /**
+     * Unattached and inactive. Any queued attach or close {@link Operation}
+     * is performed. No work can be submitted. If the {@link activate} method is
+     * called -&gt; {@link NEW}. If a attach {@link Operation} completes -&gt;
+     * {@link INACTIVE}. If a close {@link Operation} is executed -&gt;
+     * {@link CLOSING}. If {@link abort} is called -&gt; {@link ABORTING}. A
+ Session in this state is 'open'.
+     */
+    NEW_INACTIVE,
+    /**
+     * fully operational. Work is queued and performed. If {@link deactivate} is
+     * called -&gt; {@link INACTIVE}. If a close {@link Operation} is executed
+     * -&gt; {@link CLOSING}. If {@link abort} is called -&gt; {@link ABORTING}.
+ A Session in this state is both 'open' and 'active'.
+     */
+    OPEN,
+    /**
+     * Not available for new work. Queued work is performed. No work can be
+     * submitted. If the {@link activate} method is called -&gt; {@link OPEN}.
+     * If a close {@link Operation} is executed -&gt; {@link CLOSING}. If
+     * {@link abort} is called -&gt; {@link ABORTING}. A {@link Session} in
+     * this state is 'open'.
+     */
+    INACTIVE,
+    /**
+     * Work in progress is completed but no additional work is started or
+     * queued. Attempting to queue work throws {@link IllegalStateException}.
+     * When the currently executing {@link Operation}s are completed -&gt;
+     * {@link CLOSED}. All other queued Operations are completed exceptionally
+ with SqlSkippedException. A Session in this state is 'closed'.
+     */
+    CLOSING,
+    /**
+     * Work is neither queued nor performed. The currently executing
+     * {@link Operation}s, if any, are terminated, exceptionally if necessary.
+     * Any queued {@link Operation}s are terminated exceptionally with
+     * {@link SqlSkippedException}. Attempting to queue work throws
+     * {@link IllegalStateException}. When the queue is empty -&lt;
+     * {@link CLOSED}. A Session in this state is 'closed'.
+     */
+    ABORTING,
+    /**
+     * Work is neither queued nor performed. Attempting to queue work throws
+     * {@link IllegalStateException}. A Session in this state is 'closed'.
+     */
+    CLOSED;
+    
+    static {
+      NEW.init(true, true, NEW, NEW_INACTIVE, OPEN, ABORTING, CLOSING, CLOSED);
+      NEW_INACTIVE.init(true, false, NEW, NEW_INACTIVE, INACTIVE, ABORTING, CLOSING, CLOSED);
+      OPEN.init(true, true, OPEN, INACTIVE, OPEN, ABORTING, CLOSING, CLOSED);
+      INACTIVE.init(true, false, OPEN, INACTIVE, INACTIVE, ABORTING, INACTIVE, INACTIVE);
+      CLOSING.init(false, true, CLOSING, CLOSING, CLOSING, ABORTING, CLOSING, CLOSED);
+      ABORTING.init(false, true, ABORTING, ABORTING, ABORTING, ABORTING, ABORTING, CLOSED);
+      CLOSED.init(false, true, CLOSED, CLOSED, CLOSED, CLOSED, CLOSED, CLOSED);
+    }
+    
+    private boolean isOpen;
+    private boolean isActive;
+    private Lifecycle onActivate;
+    private Lifecycle onDeactivate;
+    private Lifecycle onAttach;
+    private Lifecycle onAbort;
+    private Lifecycle onClose;
+    private Lifecycle onClosed;
+    
+    private void init(boolean io, boolean ia, Lifecycle ac, Lifecycle da, Lifecycle cn, Lifecycle ab, Lifecycle cl, Lifecycle cd) {
+      isOpen = io;
+      isActive = ia;
+      onActivate = ac;
+      onDeactivate = da;
+      onAttach = cn;
+      onAbort = ab;
+      onClose = cl;
+      onClosed = cd;
+    }
+    public boolean isOpen() {
+      return isOpen;
+    }
+    
+    public boolean isActive() {
+      return isActive;
+    }
+    
+    public Lifecycle activate() {
+      return onActivate;
+    }
+    
+    public Lifecycle deactivate() {
+      return onDeactivate;
+    }
+    
+    public Lifecycle attach() {
+      return onAttach;
+    }
+    
+    public Lifecycle abort() {
+      return onAbort;
+    }
+    
+    public Lifecycle close() {
+      return onClose;
+    }
+    
+    public Lifecycle closed() {
+      return onClosed;
+    }
+  
+  }
+
+  /**
+   * Specifiers for how much effort to put into validating a {@link Session}.
+   * The amount of effort put into checking should be non-decreasing from NONE
+   * (least effort) to COMPLETE (most effort). Exactly what is checked is
+   * implementation dependent. For example, a memory resident database driver
+   * might implement SOCKET and NETWORK to be the same as LOCAL. SERVER might
+   * verify that a database manager thread is running and COMPLETE might trigger
+   * the database manager thread to run a deadlock detection algorithm.
+   */
+  public enum Validation {
+    /**
+     * isValid fails only if the {@link Session} is closed.
+     */
+    NONE,
+    /**
+     * {@link NONE} plus check local resources
+     */
+    LOCAL,
+    /**
+     * {@link LOCAL} plus the server isn't obviously unreachable (dead socket)
+     */
+    SOCKET,
+    /**
+     * {@link SOCKET} plus the network is intact (network PING)
+     */
+    NETWORK,
+    /**
+     * {@link NETWORK} plus significant server processes are running
+     */
+    SERVER,
+    /**
+     * everything that can be checked is working. At least {@link SERVER}.
+     */
+    COMPLETE;
+  }
+
+  /**
+   * A Listener that is notified of changes in a Session's lifecycle.
+   */
+  public interface SessionLifecycleListener extends java.util.EventListener {
+
+    /**
+     * If this {@link java.util.EventListener} is registered with a
+     * {@link Session} this method is called whenever that
+     * {@link Session}'s lifecycle changes. Note that the lifecycle may have
+     * changed again by the time this method is called so the
+     * {@link Session}'s current lifecycle may be different from the value of
+     * {@code current}.
+     *
+     * @param session the {@link Session}
+     * @param previous the previous value of the lifecycle
+     * @param current the new value of the lifecycle
+     */
+    public void lifecycleEvent(Session session, Lifecycle previous, Lifecycle current);
+  }
+
+  /**
+   * A {@link Session} builder. A {@link Session} is initially in the
+   * {@link Session.Lifecycle#NEW} lifecycle state. It transitions to the
+   * {@link Session.Lifecycle#OPEN} lifecycle state when fully initialized or
+   * to {@link Session.Lifecycle#CLOSED} if initialization fails.
+   *
+   */
+  public interface Builder {
+
+    /**
+     * Specify a property and its value for the built {@link Session}.
+     *
+     * @param p {@link SessionProperty} to set. Not {@code null}.
+     * @param v value for the property
+     * @return this {@link Builder}
+     * @throws IllegalArgumentException if {@code p.validate(v)} does not return
+     * true, if this method has already been called with the property
+     * {@code p}, or the implementation does not support the {@link SessionProperty}.
+     */
+    public Builder property(SessionProperty p, Object v);
+
+    /**
+     * Return a {@link Session} with the attributes specified. Note that the
+     * {@link Session} may not be attached to a server. Call one of the
+     * {@link attach} convenience methods to attach the {@link Session} to
+     * a server. The lifecycle of the new {@link Session} is
+     * {@link Lifecycle#NEW}.
+ 
+ This method cannot block. If the DataSource is unable to support a new
+ Session when this method is called, this method throws SqlException.
+ Note that the implementation does not have to allocate scarce resources to
+ the new {@link Session} when this method is called so limiting the
+     * number of {@link Session}s is not required to limit the use of
+     * scarce resources. It may be appropriate to limit the number of 
+     * {@link Session}s for other reasons, but that is implementation dependent.
+     *
+     * @return a {@link Session}
+     * @throws IllegalStateException if this method has already been called or
+ if the implementation cannot create a Session with the specified
+ {@link SessionProperty}s.
+     * @throws IllegalStateException if the {@link DataSource} that created this
+     * {@link Builder} is closed
+     * @throws SqlException if creating a {@link Session} would exceed some
+     * limit
+     */
+    public Session build();
+  }
+
+  /**
+   * Returns an {@link Operation} that attaches this {@link Session} to a
+   * data source. If the Operation completes successfully and the lifecycle is
+   * {@link Lifecycle#NEW} -&gt; {@link Lifecycle#OPEN}. If lifecycle is
+   * {@link Lifecycle#NEW_INACTIVE} -&gt; {@link Lifecycle#INACTIVE}. If the
+   * {@link Operation} completes exceptionally the lifecycle -&gt;
+   * {@link Lifecycle#CLOSED}. The lifecycle must be {@link Lifecycle#NEW} or
+   * {@link Lifecycle#NEW_INACTIVE} when the {@link Operation} is executed.
+   * Otherwise the {@link Operation} will complete exceptionally with
+   * {@link SqlException}.
+   *
+   * Note: It is highly recommended to use the {@link attach()} convenience
+   * method or to use {@link DataSource#getSession} which itself calls
+   * {@link attach()}. Unless there is a specific need, do not call this method
+   * directly.
+   *
+   * @return an {@link Operation} that attaches this {@link Session} to a
+   * server.
+   * @throws IllegalStateException if this {@link Session} is in a lifecycle
+   * state other than {@link Lifecycle#NEW}.
+   */
+  public Operation<Void> attachOperation();
+
+  /**
+   * Convenience method that supports the fluent style of the builder needed by
+   * try with resources.
+   *
+   * Note: A {@link Session} is an {@link OperationGroup} and so has some
+   * advanced features that most users do not need. Management of these features
+   * is encapsulated in this method and the corresponding {@link close()}
+   * convenience method. The vast majority of users should just use these
+   * methods and not worry about the advanced features. The convenience methods
+   * do the right thing for the overwhelming majority of use cases. A tiny
+   * number of users might want to take advantage of the advanced features that
+   * {@link OperationGroup} brings to {@link Session} and so would call
+   * {@link attachOperation} directly.
+   *
+   * @return this Session
+   * @throws IllegalStateException if this {@link Session} is in a lifecycle
+   * state other than {@link Lifecycle#NEW}.
+   */
+  public default Session attach() {
+    this.submitHoldingForMoreMembers();
+    this.attachOperation()
+            .submit();
+    return this;
+  }
+
+  /**
+   * Convenience method that supports the fluent style of the builder needed by
+   * try with resources.
+   *
+   * @param onError an Exception handler that is called if the attach
+   * {@link Operation} completes exceptionally.
+   * @return this {@link Session}
+   * @throws IllegalStateException if this {@link Session} is in a lifecycle
+   * state other than {@link Lifecycle#NEW}.
+   */
+  public default Session attach(Consumer<Throwable> onError) {
+    this.submitHoldingForMoreMembers();
+    this.attachOperation()
+            .submit()
+            .getCompletionStage()
+            .exceptionally(t -> { onError.accept(t); return null; } );
+    return this;
+  }
+
+  /**
+   * Returns an {@link Operation} that verifies that the resources are available
+   * and operational. Successful completion of that {@link Operation} implies
+   * that at some point between the beginning and end of the {@link Operation}
+ the Session was working properly to the extent specified by {@code depth}.
+   * There is no guarantee that the {@link Session} is still working after 
+   * completion. If the {@link Session} is not valid the Operation completes
+   * exceptionally.
+   *
+   * @param depth how completely to check that resources are available and
+   * operational. Not {@code null}.
+   * @return an {@link Operation} that will validate this {@link Session}
+   * @throws IllegalStateException if this Session is not active
+   */
+  public Operation<Void> validationOperation(Validation depth);
+
+  /**
+   * Convenience method to validate a {@link Session}.
+   *
+   * @param depth how completely to check that resources are available and
+   * operational. Not {@code null}.
+   * @param minTime how long to wait. If 0, wait forever
+   * @param onError called if validation fails or times out. May be
+   * {@code null}.
+   * @return this {@link Session}
+   * @throws IllegalArgumentException if {@code milliseconds} &lt; 0 or
+   * {@code depth} is {@code null}.
+   * @throws IllegalStateException if this Session is not active
+   */
+  public default Session validate(Validation depth,
+          Duration minTime,
+          Consumer<Throwable> onError) {
+    this.validationOperation(depth)
+            .timeout(minTime)
+            .onError(onError)
+            .submit();
+    return this;
+  }
+
+  /**
+   * Create an {@link Operation} to close this {@link Session}. When the
+   * {@link Operation} is executed, if this {@link Session} is open -&gt;
+   * {@link Lifecycle#CLOSING}. If this {@link Session} is closed executing
+   * the returned {@link Operation} is a no-op. When the queue is empty and all
+   * resources released -&gt; {@link Lifecycle#CLOSED}.
+   *
+   * A close {@link Operation} is never skipped. Even when the
+   * {@link Session} is dependent, the default, and an {@link Operation}
+   * completes exceptionally, a close {@link Operation} is still executed. If
+   * the {@link Session} is parallel, a close {@link Operation} is not
+   * executed so long as there are other {@link Operation}s or the
+   * {@link Session} is held for more {@link Operation}s.
+   *
+   * Note: It is highly recommended to use try with resources or the
+   * {@link close()} convenience method. Unless there is a specific need, do not
+   * call this method directly.
+   *
+   * @return an {@link Operation} that will close this {@link Session}.
+   * @throws IllegalStateException if the Session is not active
+   */
+  public Operation<Void> closeOperation();
+
+  /**
+   * Create and submit an {@link Operation} to close this {@link Session}.
+   * Convenience method.
+   *
+   * Note: A {@link Session} is an {@link OperationGroup} and so has some
+   * advanced features; that most users do not need. Management of these
+   * features is encapsulated in this method and the corresponding
+   * {@link attach()} convenience method. The vast majority of users should
+   * just use these methods and not worry about the advanced features. The
+   * convenience methods do the right thing for the overwhelming majority of use
+   * cases. A tiny number of user might want to take advantage of the advanced
+   * features that {@link OperationGroup} brings to {@link Session} and so
+   * would call {@link closeOperation} directly.
+   *
+   * @throws IllegalStateException if the Session is not active
+   */
+  @Override
+  public default void close() {
+    this.closeOperation()
+            .submit();
+    this.releaseProhibitingMoreMembers();
+  }
+
+  /**
+   * Create a new {@link OperationGroup} for this {@link Session}.
+   *
+   * @param <S> the result type of the member {@link Operation}s of the returned
+   * {@link OperationGroup}
+   * @param <T> the result type of the collected results of the member
+   * {@link Operation}s
+   * @return a new {@link OperationGroup}.
+   * @throws IllegalStateException if this Session is not active
+   */
+  public <S, T> OperationGroup<S, T> operationGroup();
+
+  /**
+   * Returns a new {@link TransactionEnd} that can be used as an argument to an
+   * endTransaction Operation.
+   *
+   * It is most likely an error to call this within an error handler, or any
+   * handler as it is very likely that when the handler is executed the next
+   * submitted endTransaction {@link Operation} will have been created with a 
+   * different TransactionEnd.
+ 
+ ISSUE: Should this be moved to OperationGroup?
+   *
+   * @return a new {@link TransactionEnd}. Not null.
+   * @throws IllegalStateException if this Session is not active
+   */
+  public TransactionEnd transactionEnd();
+  
+  /**
+   * Unconditionally perform a transaction rollback. Create an endTransaction 
+   * {@link Operation}, set it to rollback only, and submit it. The endTransaction
+   * is never skipped. Convenience method. To execute a commit call 
+   * {@link OperationGroup#commitMaybeRollback(jdk.incubator.sql2.TransactionEnd)}.
+   *
+   * @return this {@link OperationGroup}
+   * @see OperationGroup#commitMaybeRollback(jdk.incubator.sql2.TransactionEnd) 
+   */
+  public default CompletionStage<TransactionOutcome> rollback() {
+    TransactionEnd t = transactionEnd();
+    t.setRollbackOnly();
+    catchErrors();
+    return this.endTransactionOperation(t).submit().getCompletionStage();
+  }
+
+  /**
+   * Register a listener that will be called whenever there is a change in the
+   * lifecycle of this {@link Session}.If the listener is already registered
+ this is a no-op. ISSUE: Should lifecycleListener be a SessionProperty so that it is 
+ always reestablished on Session.activate?
+   *
+   * @param listener Not {@code null}.
+   * @return this Session
+   * @throws IllegalStateException if this Session is not active
+   */
+  public Session registerLifecycleListener(SessionLifecycleListener listener);
+  
+  /**
+   * Removes a listener that was registered by calling
+   * registerLifecycleListener.Sometime after this method is called the listener
+   * will stop receiving lifecycle events. If the listener is not registered,
+   * this is a no-op.
+   *
+   * @param listener Not {@code null}.
+   * @return this Session
+   * @throws IllegalStateException if this Session is not active
+   */
+  public Session deregisterLifecycleListener(SessionLifecycleListener listener);
+
+  /**
+   * Return the current lifecycle of this {@link Session}. 
+   *
+   * @return the current lifecycle of this {@link Session}.
+   */
+  public Lifecycle getSessionLifecycle();
+
+  /**
+   * Terminate this {@link Session}. If lifecycle is
+   * {@link Lifecycle#NEW}, {@link Lifecycle#OPEN}, {@link Lifecycle#INACTIVE}
+   * or {@link Lifecycle#CLOSING} -&gt; {@link Lifecycle#ABORTING} If lifecycle
+   * is {@link Lifecycle#ABORTING} or {@link Lifecycle#CLOSED} this is a no-op.
+   * If an {@link Operation} is currently executing, terminate it immediately.
+   * Remove all remaining {@link Operation}s from the queue. {@link Operation}s
+   * are not skipped. They are just removed from the queue.
+   *
+   * @return this {@link Session}
+   */
+  public Session abort();
+
+  /**
+   * Return the set of properties configured on this {@link Session}
+   * excepting any sensitive properties. Neither the key nor the value for
+   * sensitive properties are included in the result. Properties (other than
+   * sensitive properties) that have default values are included even when not
+   * explicitly set. Properties that have no default value and are not set
+   * explicitly are not included.
+   *
+   * @return a {@link Map} of property, value. Not modifiable. May be retained.
+   * Not {@code null}.
+   * @throws IllegalStateException if this Session is not active
+   */
+  public Map<SessionProperty, Object> getProperties();
+  
+  /**
+   *
+   * @return a {@link ShardingKey.Builder} for this {@link Session}
+   * @throws IllegalStateException if this Session is not active
+   */
+  public ShardingKey.Builder shardingKeyBuilder();
+
+  /**
+   * Provide a method that this {@link Session} will call to control the rate
+   * of {@link Operation} submission. This {@link Session} will call
+   * {@code request} with a positive argument when the {@link Session} 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 Session}
+   * @throws IllegalStateException if this method has been called previously or
+   * this {@link Session} is not active.
+   */
+  public Session requestHook(LongConsumer request);
+
+  /**
+   * Make this {@link Session} ready for use. A newly created
+   * {@link Session} is active. Calling this method on a {@link Session}
+   * that is active is a no-op. If the lifecycle is {@link Lifecycle#INACTIVE}
+   * -&gt; {@link Lifecycle#OPEN}. If the lifecycle is
+   * {@link Lifecycle#NEW_INACTIVE} -&gt; {@link Lifecycle#NEW}.
+   *
+   * @return this {@link Session}
+   * @throws IllegalStateException if this {@link Session} is closed.
+   */
+  public Session activate();
+
+  /**
+   * Makes this {@link Session} inactive. After a call to this method
+   * previously submitted Operations will be executed normally. If the lifecycle
+   * is {@link Lifecycle#NEW} -&gt; {@link Lifecycle#NEW_INACTIVE}. if the
+   * lifecycle is {@link Lifecycle#OPEN} -&gt; {@link Lifecycle#INACTIVE}. If
+   * the lifecycle is {@link Lifecycle#INACTIVE} or
+   * {@link Lifecycle#NEW_INACTIVE} this method is a no-op. After calling this
+   * method or calling any method other than {@link deactivate}, {@link activate},
+   * {@link abort}, or {@link getSessionLifecycle} will throw
+   * {@link IllegalStateException}. Data source state not specified
+   * by {@link Session.Builder} may not be preserved.
+   * 
+   * <p>
+   * In general {@link Session}s should not be pooled as the implementation
+   * should cache and reuse the data source resources that back {@link Session}s
+   * as appropriate, not cache the {@link Session}s themselves. 
+   * However, any {@link Session} pool is required by default to
+   * call {@code deactivate} when putting a {@link Session} into the pool. The
+   * pool is required by default to call {@code activate} when removing a
+   * {@link Session} from the pool for use. A pool may have an optional mode where
+   * it does not call {@code deactivate}/{@code activate} as required above. The
+   * behavior of the pool and {@link Session}s cached in the pool in such a
+   * mode is entirely implementation dependent.</p>
+   * 
+   * @return this {@link Session}
+   * @throws IllegalStateException if this {@link Session} is closed
+   */
+  public Session deactivate();
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SessionProperty.java	Mon Jul 09 15:09:06 2018 -0400
@@ -0,0 +1,111 @@
+/*
+ * 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;
+
+/**
+ * An attribute of a {@link Session} that can be configured to influence its
+ * behavior. Implementors of this interface define the properties of
+ * {@link Session}s. The {@link Session.Builder#property} method is used to set the values
+ * of {@link Session} properties.
+ * 
+ * Implementations must be thread safe.
+ * 
+ */
+public interface SessionProperty {
+
+  /**
+   * Return the name of this {@link SessionProperty}.
+   * 
+   * @return the name of this {@link SessionProperty}
+   */
+  public String name();
+
+  /**
+   * Return the type of the value of this {@link SessionProperty}. Any value
+   * set for this property must be assignable to this type.
+   *
+   * @return the type of the values of this {@link SessionProperty}
+   */
+  public Class<?> range();
+
+  /**
+   * Determine whether a value is valid for this {@link SessionProperty}. Returns
+   * {@code true} if {@code value} is valid and {@code false} otherwise.
+   * 
+   * @param value a value for this {@link SessionProperty}
+   * @return {@code true} iff {@code value} is valid for this {@link SessionProperty}
+   */
+  public default boolean validate(Object value) {
+    return (value == null && this.range() == Void.class) || this.range().isInstance(value);
+  }
+
+  /**
+   * Return the value for this property to use if no other value is set. For
+   * this to have any meaning for a user defined property the property must be
+   * registered with the {@link DataSource} by calling 
+   * {@link DataSource.Builder#registerSessionProperty}. 
+   *
+   * @return the default value or {@code null} if there is no default value
+   */
+  public Object defaultValue();
+
+  /**
+   * Returns true if this {@link SessionProperty} is contains sensitive information
+   * such as a password or encryption key.
+   *
+   * @return true iff this is sensitive
+   */
+  public boolean isSensitive();
+
+  /**
+   * Returns an {@link Operation} that will configure the {@link Session} to have the
+   * specified property value.May return {@code null} if no {@link Operation} needed. The
+ returned {@link Operation} is a member of group but is not submitted.
+   *
+   * Called by {@link Session.Builder#build()} to configure a {@link Session} as specified
+   * in the {@link Session.Builder#property} method. SessionProperties known to the implementation
+   * may return {@code null} and rely on the implementation to do the right thing.
+   *
+   * @param <S>
+   * @param group an {@link OperationGroup} which will be the container of the returned
+   * {@link Operation}, if any
+   * @param value the value to which the property is to be set. May be null if
+   * {@link range()} is {@link Void}.
+   * @return an {@link Operation} or null
+   * @throws IllegalStateException if it is not possible to configure the
+   * {@link Session} as specified.
+   * @throws IllegalArgumentException if {@code this.validate(value)} returns {@code false}
+   */
+  public default <S> Operation<? extends S> configureOperation(OperationGroup<S, ?> group, Object value) {
+    if (validate(value)) {
+      return null;
+    }
+    else {
+      throw new IllegalArgumentException(value.toString() + " is invalid");
+    }
+  }
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ShardingKey.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/ShardingKey.java	Mon Jul 09 15:09:06 2018 -0400
@@ -45,14 +45,14 @@
  * <p>
  *
  * A {@link ShardingKey} is used for specifying a
- * {@link AdbaConnectionProperty#SHARDING_KEY} or a
- * {@link AdbaConnectionProperty#SHARDING_GROUP_KEY}. Databases that support
+ * {@link AdbaSessionProperty#SHARDING_KEY} or a
+ * {@link AdbaSessionProperty#SHARDING_GROUP_KEY}. Databases that support
  * composite Sharding may use a * to specify a additional level of partitioning
  * within to specify a additional level of partitioning within the Shard.
  * <p>
  * The following example illustrates the use of {@link Builder} to create a
- * {@link AdbaConnectionProperty#SHARDING_GROUP_KEY} for an eastern region with
- * a {@link AdbaConnectionProperty#SHARDING_KEY} specified for the Pittsburgh
+ * {@link AdbaSessionProperty#SHARDING_GROUP_KEY} for an eastern region with
+ * a {@link AdbaSessionProperty#SHARDING_KEY} specified for the Pittsburgh
  * branch office:
  * <pre>
  * {@code
@@ -64,7 +64,7 @@
  *     ShardingKey shardingKey = ds.shardingKeyBuilder()
  *                           .subkey("PITTSBURGH_BRANCH", JDBCType.VARCHAR)
  *                           .build();
- *     Connection con = ds.builder()
+ *     Session con = ds.builder()
  *                           .property(SHARDING_GROUP_KEY, superShardingKey)
  *                           .property(SHARDING_KEY, shardingKey)
  *                           .build();
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlBlob.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlBlob.java	Mon Jul 09 15:09:06 2018 -0400
@@ -56,7 +56,7 @@
    * Position is between 0 and length + 1.
    *
    * @return a {@link Operation} that returns the position of this {@link SqlBlob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public Operation<Long> getPositionOperation();
@@ -73,7 +73,7 @@
    * does?
    *
    * @return a future which value is the 1-based position of this {@link SqlBlob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public default CompletionStage<Long> getPosition() {
@@ -84,7 +84,7 @@
    * Return a {@link Operation} that fetches the length of this {@link SqlBlob}.
    *
    * @return a {@link Operation} that returns the length of this {@link SqlBlob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public Operation<Long> lengthOperation();
@@ -93,7 +93,7 @@
    * Get the length of this {@link SqlBlob}.
    *
    * @return a future which value is the number of bytes in this {@link SqlBlob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public default CompletionStage<Long> length() {
@@ -108,7 +108,7 @@
    * @param offset a non-negative number
    * @return a {@link Operation} that sets the position of this {@link SqlBlob}
    * @throws IllegalArgumentException if {@code offset} is less than 0
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public Operation<Long> setPositionOperation(long offset);
@@ -121,7 +121,7 @@
    * @param offset the 1-based position to set
    * @return this {@link SqlBlob}
    * @throws IllegalArgumentException if offset is less than 0
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public default SqlBlob setPosition(long offset) {
@@ -134,13 +134,13 @@
    * occurrence of the target after the position. If there is no such occurrence
    * set the position to 0.
    *
-   * @param target a {@link SqlBlob} created by the same {@link Connection}
+   * @param target a {@link SqlBlob} created by the same {@link Session}
    * containing the byte sequence to search for
    * @return a {@link Operation} that locates {@code target} in this
    * {@link SqlBlob}
    * @throws IllegalArgumentException if {@code target} was created by some
-   * other {@link Connection}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * other {@link Session}
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public Operation<Long> locateOperation(SqlBlob target);
@@ -152,8 +152,8 @@
    * @param target the byte sequence to search for
    * @return this {@link SqlBlob}
    * @throws IllegalArgumentException if {@code target} was created by some
-   * other {@link Connection}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * other {@link Session}
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed
    */
   public default SqlBlob locate(SqlBlob target) {
@@ -169,7 +169,7 @@
    * @param target the byte sequence to search for. Not {@code null}. Captured.
    * @return a {@link Operation} that locates {@code target} in this
    * {@link SqlBlob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public Operation<Long> locateOperation(byte[] target);
@@ -180,7 +180,7 @@
    *
    * @param target the byte sequence to search for
    * @return this {@link SqlBlob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public default SqlBlob locate(byte[] target) {
@@ -195,7 +195,7 @@
    * will fail if position is 0.
    *
    * @return a {@link Operation} that trims the length of this {@link SqlBlob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed or position is 0.
    */
   public Operation<Long> trimOperation();
@@ -206,7 +206,7 @@
    * N - 1. The position is still N. This will fail if position is 0.
    *
    * @return this SqlBlob
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed or position is 0.
    */
   public default SqlBlob trim() {
@@ -225,7 +225,7 @@
    * may be skipped if an error occurs.
    *
    * @return a read-only byte {@link java.nio.channels.Channel} beginning at the position.
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
  SqlBlob is closed.
    */
   public AsynchronousByteChannel getReadChannel();
@@ -248,7 +248,7 @@
    *
    * @return a writable byte {@link java.nio.channels.Channel} beginning at the
    * position.
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlBlob} is closed.
    */
   public AsynchronousByteChannel getWriteChannel();
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlClob.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlClob.java	Mon Jul 09 15:09:06 2018 -0400
@@ -57,7 +57,7 @@
    * Position is between 0 and length + 1.
    *
    * @return an {@link Operation} that returns the position of this {@link SqlClob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.;
    */
   public Operation<Long> getPositionOperation();
@@ -73,7 +73,7 @@
  does?
    *
    * @return a future which value is the position of this {@link SqlClob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.
    */
   public default CompletionStage<Long> getPosition() {
@@ -84,7 +84,7 @@
    * Return a {@link Operation} that fetches the length of this {@link SqlClob}.
    *
    * @return a {@link Operation} that returns the length of this {@link SqlClob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.
    */
   public Operation<Long> lengthOperation();
@@ -94,7 +94,7 @@
    *
    * @return a {@link java.util.concurrent.Future} which value is the number of
    * chars in this {@link SqlClob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.
    */
   public default CompletionStage<Long> length() {
@@ -109,7 +109,7 @@
    * @param offset a non-negative number
    * @return a {@link Operation} that sets the position of this {@link SqlClob}
    * @throws IllegalArgumentException if {@code offset} is less than 0
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.
    */
   public Operation<Long> setPositionOperation(long offset);
@@ -122,7 +122,7 @@
    * @param offset the 1-based position to set
    * @return this {@link SqlClob}
    * @throws IllegalArgumentException if {@code offset} is less than 0
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.
    */
   public default SqlClob setPosition(long offset) {
@@ -135,13 +135,13 @@
    * next occurrence of the target after the position. If there is no such
    * occurrence set the position to 0.
    *
-   * @param target a {@link SqlClob} created by the same {@link Connection}
+   * @param target a {@link SqlClob} created by the same {@link Session}
    * containing the char sequence to search for
    * @return an {@link Operation} that locates {@code target} in this
    * {@link SqlClob}
    * @throws IllegalArgumentException if {@code target} was created by some
-   * other {@link Connection}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * other {@link Session}
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.
    */
   public Operation<Long> locateOperation(SqlClob target);
@@ -153,8 +153,8 @@
    * @param target the char sequence to search for
    * @return this {@link SqlClob}
    * @throws IllegalArgumentException if {@code target} was created by some
-   * other {@link Connection}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * other {@link Session}
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed
    */
   public default SqlClob locate(SqlClob target) {
@@ -170,7 +170,7 @@
    * @param target the char sequence to search for. Not {@code null}. Captured.
    * @return an {@link Operation} that locates {@code target} in this
    * {@link SqlClob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.
    */
   public Operation<Long> locateOperation(CharSequence target);
@@ -181,7 +181,7 @@
    *
    * @param target the char sequence to search for
    * @return this {@link SqlClob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed.
    */
   public default SqlClob locate(CharSequence target) {
@@ -196,7 +196,7 @@
    * if position is 0.
    *
    * @return an {@link Operation} that trims the length of this {@link SqlClob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed or position is 0.
    */
   public Operation<Long> trimOperation();
@@ -207,7 +207,7 @@
    * N - 1. The position is still N. This will fail if position is 0.
    *
    * @return this {@link SqlClob}
-   * @throws IllegalStateException if the {@link Connection} that created this
+   * @throws IllegalStateException if the {@link Session} that created this
    * {@link SqlClob} is closed or position is 0.
    */
   public default SqlClob trim() {
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlType.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/SqlType.java	Mon Jul 09 15:09:06 2018 -0400
@@ -26,7 +26,10 @@
 package jdk.incubator.sql2;
 
 /**
- * Remove dependence on java.sql.
+ * Identifies a SQL type. Can be a type defined by standard SQL or a vendor
+ * specific type.
+ * 
+ * @see AdbaType
  */
 public interface SqlType {
 
@@ -43,14 +46,8 @@
   public String getVendor();
 
   /**
-   *
-   * @return
-   */
-  public Integer getVendorTypeNumber();
-  
-  /**
    * 
-   * @return Java type
+   * @return a Java type that best represents values of this SQL type
    */
   public <T> Class<T> getJavaType();
 }
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Transaction.java	Fri Jul 06 20:37:32 2018 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +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;
-
-/**
- * A mutable object that controls whether a transactionEnd Operation sends
- * a database commit or a database rollback to the server. A transactionEnd
- * Operation is created with a Transaction. By default a transactionEnd
- * Operation requests that the database end the transaction with a commit.
- * If Transaction#setRollbackOnly is called on the Transaction used to create
- * the Operation prior to the Operation being executed, the Operation will
- * request that the database end the transaction with a rollback.
- * 
- * Example:
- *
- * <pre>
- * {@code
- *   Transaction t = conn.transaction();
- *   conn.countOperation(updateSql)
- *       .resultProcessor( count -> { if (count > 1) t.setRollbackOnly(); } )
- *       .submit();
- *   conn.commit(t);
- * }</pre>
- *
- * A Transaction can not be used to create more than one endTransaction 
- * Operation.
- * 
- * A Transaction is thread safe.
- */
-public interface Transaction {
-
-  /**
-   * Causes an endTransactionOperation created with this Transaction that is executed
-   * subsequent to this call to perform a rollback. If this method is not called
-   * prior to Operation execution the Operation will perform a commit.
-   *
-   * @return true if the call succeeded. False if the call did not succeed in
-   * setting the Transaction rollback only because the endTransaction
-   * Operation had already been executed.
-   */
-  public boolean setRollbackOnly();
-
-  /**
-   * Returns {@code true} iff the {@link setRollbackOnly} method has been called
-   * on this Transaction
-   *
-   * @return {@code true} if {@link setRollbackOnly} has been called.
-   */
-  public boolean isRollbackOnly();
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/TransactionEnd.java	Mon Jul 09 15:09:06 2018 -0400
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+/**
+ * A mutable object that controls whether a transactionEnd Operation sends
+ * a database commit or a database rollback to the server. A transactionEnd
+ * Operation is created with a TransactionEnd. By default a transactionEnd
+ * Operation requests that the database end the transaction with a commit.
+ * If {@link TransactionEnd#setRollbackOnly} is called on the TransactionEnd used to create
+ * the Operation prior to the Operation being executed, the Operation will
+ * request that the database end the transaction with a rollback.
+ * 
+ * Example:
+ *
+ * <pre>
+ * {@code
+   TransactionEnd t = session.transactionEnd();
+   session.countOperation(updateSql)
+       .resultProcessor( count -> { if (count > 1) t.setRollbackOnly(); } )
+       .submit();
+   session.commitMaybeRollback(t);
+ }</pre>
+
+ A TransactionEnd can not be used to create more than one endTransaction 
+ Operation.
+ 
+ A TransactionEnd is thread safe.
+ * 
+ * ISSUE: The name is terrible. Please suggest a better alternative, TransactionLatch?
+ */
+public interface TransactionEnd {
+
+  /**
+   * Causes an endTransactionOperation created with this TransactionEnd that is executed
+   * subsequent to this call to perform a rollback. If this method is not called
+   * prior to Operation execution the Operation will perform a commit.
+   *
+   * @return true if the call succeeded. False if the call did not succeed in
+ setting the TransactionEnd rollback only because the endTransaction
+ Operation had already been executed.
+   */
+  public boolean setRollbackOnly();
+
+  /**
+   * Returns {@code true} iff the {@link setRollbackOnly} method has been called
+ on this TransactionEnd
+   *
+   * @return {@code true} if {@link setRollbackOnly} has been called.
+   */
+  public boolean isRollbackOnly();
+
+}
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java	Fri Jul 06 20:37:32 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java	Mon Jul 09 15:09:06 2018 -0400
@@ -102,20 +102,28 @@
  * executed regardless of whether one or more fails.</p>
  *
  * <p>
- * A {@link Connection} is itself an {@link OperationGroup} and so can be
+ * A single context in a data source is represented by a {@link Session}. A 
+ * {@link Session} is somewhat analogous to a logical {@link java.sql.Connection}.
+ * A physical {@link java.sql.Connection} has no representation in this API; if
+ * such an entity exists at all it is strictly internal to an implementation.
+ * Within this spec this entity is referred to as a "data source resource".
+ * </p>
+ * 
+ * <p>
+ * A {@link Session} is itself an {@link OperationGroup} and so can be
  * conditional, parallel, or independent, but by default is unconditional,
- * sequential, dependent. While a {@link Connection} may be created with values
+ * sequential, dependent. While a {@link Session} may be created with values
  * other than the defaults, using the defaults is by far the most common case.
  * The API provides convenience methods that support this case. Using these
  * convenience methods is recommended in all but the most unusual circumstances.
- * In particular making the {@link Connection} parallel introduces some
+ * In particular making the {@link Session} parallel introduces some
  * challenges that would require a full understanding of the details of the API.
  * It would almost certainly be better to create a parallel
- * {@link OperationGroup} within the {@link Connection}.</p>
+ * {@link OperationGroup} within the {@link Session}.</p>
  *
  * <p>
  * <i>
- * ISSUE: Should we disallow {@code Connection.parallel()}?</i></p>
+ * ISSUE: Should we disallow {@code Session.parallel()}?</i></p>
  *
  * <p>
  * The {@code java.sql} API frequently provides many ways to do the same thing.
@@ -187,7 +195,9 @@
  * 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  {@link UnsupportedOperationException} if 
- * {@link Operation#timeout} is called.</p>
+ * {@link Operation#timeout} is called. To this end every type and method is 
+ * optional except returning a {@link DataSourceFactory} in response to a call to 
+ * {@link DataSourceFactory#newFactory} with the appropriate name.</p>
  *
  * <h3>Execution Model</h3>
  *
@@ -205,9 +215,8 @@
  * An {@link Operation} is executed by causing the action to be performed,
  * processing the result of the action if there is a result processor, and
  * completing the {@link java.util.concurrent.CompletionStage} with the result
- * 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
+ * of the result processor if there is one. If the action or the result processing
+ * causes an unhandled error the {@link java.util.concurrent.CompletionStage} is
  * 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}.
@@ -216,10 +225,11 @@
  * <p>
  * Performing the action may require one or more interactions with the database.
  * These interactions may be carried out in parallel with processing the result.
- * If the database result is ordered, that result is processed in that order.
+ * If the database result is ordered, that result is processed in the order
+ * specified by the database.</p>
  *
  * <p>
- * An {@link OperationGroup} has a collection of {@link Operation}s and
+ * An {@link OperationGroup} has a collection of member {@link Operation}s and
  * optionally a condition. For a sequential {@link OperationGroup}
  * {@link Operation}s are selected from the collection in the order they were
  * submitted. For a parallel {@link OperationGroup} {@link Operation}s are
@@ -255,13 +265,13 @@
  * {@link Operation} to complete exceptionally. 
  * 
  * <p>
- * Note: the {@link Operation}s returned by {@link Connection#closeOperation}
+ * Note: the {@link Operation}s returned by {@link Session#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 
  * 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>
+ * {@link Session#closeOperation} has been submitted.</p> </li>
  * <li>
  * If the {@link OperationGroup} is independent and an {@link Operation}
  * completes exceptionally all other {@link Operation}s are executed regardless.
@@ -271,8 +281,8 @@
  * </ul>
  *
  * <p>
- * A {@link Connection} is a distinguished {@link OperationGroup}. A
- * {@link Connection} is executed upon being submitted.</p>
+ * A {@link Session} is a distinguished {@link OperationGroup}. A
+ * {@link Session} is executed upon being submitted.</p>
  *
  * <h3>Transactions</h3>
  *
@@ -293,45 +303,47 @@
  * <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 submitted.
- * But if the execution of the transaction does not result in the expected results
+ * 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
- * endTransaction Operation is created. To address this mismatch, the endTransaction Operation
- * specified by this API is conditioned by a {@link Transaction}. By default, a 
- * {@link Transaction} will cause an endTransaciton {@link Operation} to commit 
- * the transaction. At any time before the endTransaction {@link Operation} that 
- * references it is executed a {@link Transaction} can be set
- * to rollback the transaction .</p>
+ * endTransaction Operation is submitted. To address this mismatch, the
+ * endTransaction Operation is conditioned by a {@link TransactionEnd}. By
+ * default, a {@link TransactionEnd} will cause an endTransaciton
+ * {@link Operation} to commit the transaction. At any time before the
+ * endTransaction {@link Operation} that references it is executed a
+ * {@link TransactionEnd} can be set to rollback the transaction .</p>
  *
  * <p>
- * An endTransaction {@link Operation}, like all {@link Operation}s, is immutable once submitted.
- * But an endTransaction {@link Operation} is created with a {@link Transaction} and that
- * {@link Transaction} can be set to commit or rollback. A {@link Transaction} controls the
- * endTransaction {@link Operation} created with it. Using this mechanism an
- * error handler, result handler or other code can cause a subsequent endTransaction
+ * An endTransaction {@link Operation}, like all {@link Operation}s, is
+ * immutable once submitted. But an endTransaction {@link Operation} is created
+ * with a {@link TransactionEnd} and that {@link TransactionEnd} can be set to
+ * commit or rollback. A {@link TransactionEnd} controls the endTransaction
+ * {@link Operation} created with it. Using this mechanism an error handler,
+ * result handler or other code can cause a subsequent endTransaction
  * {@link Operation} to rollback instead of the default which is to commit.</p>
  *
  * <pre>
  * {@code
- *   Transaction t = conn.getTransaction();
- *   conn.countOperation(updateSql)
+ *   TransactionEnd t = session.getTransactionEnd();
+ *   session.countOperation(updateSql)
  *       .resultProcessor( count -> { 
  *           if (count > 1) t.setRollbackOnly(); 
  *           return null; 
  *       } )
  *       .submit();
- *   conn.catchErrors();
- *   conn.commitMaybeRollback(t);
+ *   session.catchErrors();
+ *   session.commitMaybeRollback(t);
  * }
  * </pre>
  *
  * <p>
  * In this example if the update SQL modifies more than one row the result
- * processor will set the Transaction to rollback only. When the endTransaction
- * Operation submitted by commitMaybeRollback is executed it will cause
- * the transaction to rollback.</p>
- * 
+ * processor will set the {@link TransactionEnd} to rollback only. When the
+ * endTransaction {@link Operation} submitted by
+ * {@link OperationGroup#commitMaybeRollback} is executed it will cause the
+ * transaction to rollback.</p>
+ *
  *
  * <h3>Implementation Note</h3>
  * 
@@ -344,18 +356,18 @@
  * 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
+ * also have to expose FooDataSource, FooOperationGroup and FooSession. 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>FooDataSource must override builder to return FooSession.Builder</li>
+ * <li>FooSession.Builder must override url, password, etc to return a 
+ * FooSession.Builder. build must return a FooSession</li>
+ * <li>FooDataSource must override getSession to return FooSession</li>
+ * <li>FooSession 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>
@@ -369,8 +381,8 @@
  *   FooDataSource dataSource = factory.builder()
  *       .url("scott/tiger@host:port")
  *       .build();
- *   FooConnection conn = dataSource.getConnection();
- *   CompletionStage<Long> count = conn.rowOperation(sql)
+ *   FooSession session = dataSource.getSession();
+ *   CompletionStage<Long> count = session.rowOperation(sql)
  *       .set("param", value, AdbaType.VARCHAR)
  *       .foo()
  *       .submit()