src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/package-info.java
author lancea
Wed, 11 Jul 2018 19:36:23 -0400
branchJDK-8188051-branch
changeset 56828 64304e37e9b1
parent 56824 62e92191354d
child 56832 4f7713e6a308
permissions -rw-r--r--
JDK-8188051-branch javadoc updates and added TransactionCompletion.java

/*
 * 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.
 */


/**
 * <p>
 * An API for accessing and processing data stored in a data source (usually a
 * relational database) using the Java&trade; programming language. This API
 * includes a framework whereby different drivers can be installed dynamically
 * to access different data sources. This API is specifically geared for passing
 * SQL statements to a database though it may be used for reading and writing
 * data from/to any data source that has a tabular format.</p>
 *
 * <p>
 * This API differs from the API in {@code java.sql} in several ways.</p>
 * <ul>
 * <li>Is asynchronous
 * <li>Is geared toward high-throughput programs
 * <li>Does not attempt to support every database feature
 * <li>Does not attempt to abstract the database
 * <li>Uses the builder pattern
 * <li>Supports the fluent programming style
 * </ul>
 *
 * <p>
 * It is worth emphasizing that this API is an alternate to the {@code java.sql}
 * API, not a replacement. There are many programs that can much more readily be
 * written using the {@code java.sql} API as it has many features that are not
 * available in this API. For example this API provides almost no mechanism for
 * getting metadata.</p>
 *
 * <p>
 * This API is not an extension to the {@code java.sql} API. It an independent
 * API and is used on its own without reference to java.sql. </p>
 *
 *
 * <h3>Overview</h3>
 *
 * <p>
 * The core feature of this API is that it is asynchronous. No method call will 
 * wait for a network operation. </p>
 *
 * <p>
 * Possibly blocking actions are represented as {@link Operation}s. An
 * application using the API creates and submits one or more {@link Operation}s.
 * The implementation executes these {@link Operation}s asynchronously, reporting 
 * their results via {@link java.util.concurrent.CompletionStage}s. An application
 * can respond to the results via the
 * {@link java.util.concurrent.CompletionStage}s or via callbacks that can be
 * configured on many of the {@link Operation}s or both. Creating and submitting
 * {@link Operation}s is strictly non-blocking. Handling the results of possibly
 * blocking {@link Operation}s is done asynchronously. No application thread
 * will ever block on a call to a method in this API.</p>
 *
 * <p>
 * All {@link Operation}s provide a
 * {@link java.util.concurrent.CompletionStage}. The value of that
 * {@link java.util.concurrent.CompletionStage} is the value of the
 * {@link Operation}, set when the {@link Operation} completes. Some
 * {@link Operation}s provide callbacks for processing the result of the
 * {@link Operation} independent of the
 * {@link java.util.concurrent.CompletionStage}. Those {@link Operation}s can
 * be used for executing SQL that returns results of a specific type. For
 * example SQL that returns a row sequence would be executed with a
 * {@link RowOperation}. A {@link RowOperation} provides callbacks for
 * processing each row and for collecting the results of processing the rows.
 * Other {@link Operation}s are specialized for SQL that returns a count or that
 * returns out parameters. The choice of {@link Operation} is dependent on the
 * result to be processed and is independent of the particular kind of SQL
 * statement.</p>
 *
 * <p>
 * An {@link OperationGroup} encapsulates a group of {@link Operation}s and
 * executes them using common attributes. An {@link OperationGroup} can be
 * unconditional or conditional, sequential or parallel, dependent or
 * independent, or any combination of these. Dependent/independent controls
 * error handling. If one member of a dependent {@link OperationGroup} fails the
 * remaining not-yet-executed members are completed exceptionally. If the
 * {@link OperationGroup} is independent, the member {@link Operation}s are
 * executed regardless of whether one or more fails.</p>
 *
 * <p>
 * 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 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 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 Session}.</p>
 *
 * <p>
 * <i>
 * ISSUE: Should we disallow {@code Session.parallel()}?</i></p>
 *
 * <p>
 * The {@code java.sql} API frequently provides many ways to do the same thing.
 * This API makes no attempt to do this. For those capabilities this API
 * supports, it frequently defines exactly one way to do something. Doing things
 * another way, for example calling methods in a non-standard order, frequently
 * results in an IllegalStateException. This approach is intended to make things
 * simpler for both the user and the implementor. Rather than having to
 * understand complicated interactions of many different components and methods
 * executed in any order, the intent is that there is only one way to do things
 * so only one path must be understood or implemented. Anything off that path is
 * an error. While this requires a programmer to write code in one specific way
 * it makes things easier on future maintainers of the code as the code will
 * conform to the standard pattern. Similarly the implementation is simplified
 * as only the standard use pattern is supported.</p>
 *
 * <p>
 * One way this API simplifies things in to define types as single use. Many
 * types are created, configured, used once, and are then no longer usable. Most
 * configuration methods can be called only once on a given instance. Once an
 * instance is configured it cannot be reconfigured. Once an instance is used it
 * cannot be reused. This simplifies things by eliminating the need to
 * understand and implement arbitrary sequences of method calls that reconfigure
 * and reuse instances. Since objects are single use there is no expectation
 * that an application cache or share {@link Operation}s.</p>
 *
 * <p>
 * While the user visible types are single use, it is expected that an
 * implementation will cache and reuse data and {@link Object}s that are worth
 * the effort. Rather than attempt to guess what an implementation should reuse
 * and capture that in the API, this API leaves it entirely up to the
 * implementation. Since the API specifies very little reuse, an implementation
 * is free to reuse whatever is appropriate. Since the pattern of use is
 * strictly enforced figuring out how to reuse objects is greatly
 * simplified.</p>
 *
 * <p>
 * The {@code java.sql} API provides many tools for abstracting the database,
 * for enabling the user to write database independent code. This API does not.
 * It is not a goal of this API to enable users to write database independent
 * code. That is not to say it is not possible, just that this API does not
 * provide tools to support such. Abstraction features typically impose
 * performance penalties on some implementations. As this API is geared for
 * high-throughput programs it avoids such abstractions rather than reduce
 * performance.</p>
 *
 * <p>
 * One such abstraction feature is the JDBC escape sequences. Implementing these
 * features requires parsing the SQL so as to identify the escape sequences and
 * then generating a new String with the vendor specific SQL corresponding to
 * the escape sequence. This is an expensive operation. Further each SQL must be
 * parsed whether it contains an escape sequence or not imposing the cost on all
 * JDBC users, not just the ones who use escape sequences. The same is true of
 * JDBC parameter markers. The SQL accepted by this API is entirely vendor
 * specific, including parameter markers. There is no need for pre-processing
 * prior to SQL execution substantially reducing the amount of work the
 * implementation must do.</p>
 *
 * <p>
 * Note: It would be a reasonable future project to develop a SQL builder API
 * that creates vendor specific SQL from some more abstract representation.</p>
 * 
 * <p>
 * This API is targeted at high-throughput apps. If a particular feature of this
 * API would have a surprising performance impact for a particular implementation
 * it is recommended that the implementation not implement that feature. It is
 * better that a feature be unsupported as opposed to users investing substantial
 * effort in an app using that feature only to discover in production that the
 * performance is unacceptable. For example, if an implementation can only support
 * {@link Operation#timeout} through active polling it would be better for that
 * implementation to throw  {@link UnsupportedOperationException} if 
 * {@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>
 *
 * <p>
 * <i>This section describes the function of a conforming implementation. It is
 * not necessary for an implementation to be implemented as described only that
 * the behavior be the same.</i></p>
 *
 * <p>
 * An {@link Operation} has an action and a
 * {@link java.util.concurrent.CompletionStage}. Some {@link Operation}s have
 * some form of result processor.</p>
 *
 * <p>
 * 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. 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}.
 * </p>
 *
 * <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 the order
 * specified by the database.</p>
 *
 * <p>
 * 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
 * selected from the collection in any order.</p>
 *
 * <p>
 * The action of an {@link OperationGroup} is performed as follows:
 * <ul>
 * <li>
 * If the {@link OperationGroup} has a condition, the value of the condition is
 * retrieved. If the value is {@link Boolean#FALSE} the action is complete and
 * the {@link java.util.concurrent.CompletionStage} is completed with null. If
 * the condition value completes exceptionally the action is complete and the
 * {@link java.util.concurrent.CompletionStage} is completed exceptionally
 * with the same exception. If the condition value is {@link Boolean#TRUE} or
 * there is no condition the {@link Operation}s in the collection are executed
 * and their results processed. The action is complete when the
 * {@link OperationGroup} is not held and all the {@link Operation}s have been
 * executed.</li>
 * <li>
 * If the {@link OperationGroup} is parallel more than one member
 * {@link Operation} may be executed at a time.</li>
 * <li>
 * If the {@link OperationGroup} is dependent and a member {@link Operation} completes
 * exceptionally all member {@link Operation}s that are yet to begin
 * execution are completed exceptionally with a {@link SqlSkippedException}. The
 * cause of that exception is the {@link Throwable} that caused the
 * {@link Operation} to be completed exceptionally. If an {@link Operation} is
 * in flight when another {@link Operation} completes exceptionally the in
 * flight {@link Operation} may either be allowed to complete uninterrupted or
 * it may be completed exceptionally. The {@link OperationGroup} is dependent it
 * is completed exceptionally with the {@link Throwable} that caused the 
 * {@link Operation} to complete exceptionally. 
 * 
 * <p>
 * Note: the {@link Operation}s returned by {@link 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 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.
 * There is no result to be processed for an {@link Operation} that completed
 * exceptionally. The {@link OperationGroup} is not completed exceptionally as
 * the result of one or more {@link Operation}s completing exceptionally.</li>
 * </ul>
 *
 * <p>
 * A {@link Session} is a distinguished {@link OperationGroup}. A
 * {@link Session} is executed upon being submitted.</p>
 *
 * <h3>Transactions</h3>
 *
 * <p>
 * <i>This section describes the function of a conforming implementation. It is
 * not necessary for an implementation to be implemented as described only that
 * the behavior be the same.</i></p>
 *
 * <p>
 * An implementation has only limited control over transactions. SQL statements
 * can start, commit, and rollback transactions without the implementation
 * having any influence or even being aware. This specification only describes
 * the behavior of those transaction actions that are visible to and controlled
 * by the implementation, i.e. the endTransaction {@link Operation}.
 * Transaction actions caused by SQL may interact with actions controlled by the
 * implementation in unexpected ways.</p>
 *
 * <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
 * 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 submitted. To address this mismatch, the
 * endTransaction Operation is conditioned by a {@link TransactionCompletion}. By
 * default, a {@link TransactionCompletion} 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 TransactionCompletion} 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 TransactionCompletion} and that {@link TransactionCompletion} can be set to
 * commit or rollback. A {@link TransactionCompletion} 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
 *   TransactionCompletion t = session.getTransactionEnd();
 *   session.countOperation(updateSql)
 *       .resultProcessor( count -> { 
 *           if (count > 1) t.setRollbackOnly(); 
 *           return null; 
 *       } )
 *       .submit();
 *   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 {@link TransactionCompletion} 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>
 * 
 * <p>
 * If an implementation exposes any implementation specific types and methods, the
 * implementation is expected to provide covariant overrides for all methods that
 * return the standard super-type of the implementation specific type.</p>
 * 
 * <p>
 * Consider an implementation that adds a method foo() to RowCountOperation. To do
 * that it would have to expose a type FooRowCountOperation extends RowCountOperation.
 * So that an application can transparently access foo, the implementation would
 * also have to expose FooDataSource, FooOperationGroup and 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 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>
 * <p>
 * The intent is to transparently expose the vendor extension without use of casts.
 * Example: </p>
 * 
 * <pre>
 * {@code
 *   FooDataSourceFactory factory = DataSourceFatory.newFactory("com.foo.FooDataSourceFatory");
 *   FooDataSource dataSource = factory.builder()
 *       .url("scott/tiger@host:port")
 *       .build();
 *   FooSession session = dataSource.getSession();
 *   CompletionStage<Long> count = session.rowOperation(sql)
 *       .set("param", value, AdbaType.VARCHAR)
 *       .foo()
 *       .submit()
 *       .getCompletionStage();
 * }
 * </pre>
 * 
 * <p>
 * Notice that there are no casts, yet both standard methods an the vendor extension
 * method foo can be referenced. This is possible only if the implementation exposes
 * all the necessary types and provides covariant overrides for every method that
 * returns one of those types. Implementations are expected (required?) to do this.
 * </p>
 * 
 * <p>
 * If an implementation does not expose any implementation specific methods or 
 * types, that implementation is not required to provide covariant overrides that
 * return implementation specific types.</p>
 * 
 * 
 */
 package jdk.incubator.sql2;