--- /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
- * -> {@link OPEN}. If {@link deactivate} is called ->
- * {@link NEW_INACTIVE}. If {@link abort} is called -> {@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 -> {@link NEW}. If a connect {@link Operation} completes ->
- * {@link INACTIVE}. If a close {@link Operation} is executed ->
- * {@link CLOSING}. If {@link abort} is called -> {@link ABORTING}. A
- * Connection in this state is 'open'.
- */
- NEW_INACTIVE,
- /**
- * fully operational. Work is queued and performed. If {@link deactivate} is
- * called -> {@link INACTIVE}. If a close {@link Operation} is executed
- * -> {@link CLOSING}. If {@link abort} is called -> {@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 -> {@link OPEN}.
- * If a close {@link Operation} is executed -> {@link CLOSING}. If
- * {@link abort} is called -> {@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 ->
- * {@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 -<
- * {@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} -> {@link Lifecycle#OPEN}. If lifecycle is
- * {@link Lifecycle#NEW_INACTIVE} -> {@link Lifecycle#INACTIVE}. If the
- * {@link Operation} completes exceptionally the lifecycle ->
- * {@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} < 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 ->
- * {@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 -> {@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} -> {@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}
- * -> {@link Lifecycle#OPEN}. If the lifecycle is
- * {@link Lifecycle#NEW_INACTIVE} -> {@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} -> {@link Lifecycle#NEW_INACTIVE}. if the
- * lifecycle is {@link Lifecycle#OPEN} -> {@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><List<Integer>></b>arrayCountOperation(sql)
+ * session.<b><List<Integer>></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
+ * -> {@link OPEN}. If {@link deactivate} is called ->
+ * {@link NEW_INACTIVE}. If {@link abort} is called -> {@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 -> {@link NEW}. If a attach {@link Operation} completes ->
+ * {@link INACTIVE}. If a close {@link Operation} is executed ->
+ * {@link CLOSING}. If {@link abort} is called -> {@link ABORTING}. A
+ Session in this state is 'open'.
+ */
+ NEW_INACTIVE,
+ /**
+ * fully operational. Work is queued and performed. If {@link deactivate} is
+ * called -> {@link INACTIVE}. If a close {@link Operation} is executed
+ * -> {@link CLOSING}. If {@link abort} is called -> {@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 -> {@link OPEN}.
+ * If a close {@link Operation} is executed -> {@link CLOSING}. If
+ * {@link abort} is called -> {@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 ->
+ * {@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 -<
+ * {@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} -> {@link Lifecycle#OPEN}. If lifecycle is
+ * {@link Lifecycle#NEW_INACTIVE} -> {@link Lifecycle#INACTIVE}. If the
+ * {@link Operation} completes exceptionally the lifecycle ->
+ * {@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} < 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 ->
+ * {@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 -> {@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} -> {@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}
+ * -> {@link Lifecycle#OPEN}. If the lifecycle is
+ * {@link Lifecycle#NEW_INACTIVE} -> {@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} -> {@link Lifecycle#NEW_INACTIVE}. if the
+ * lifecycle is {@link Lifecycle#OPEN} -> {@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()