src/java.sql/share/classes/java/sql2/OperationGroup.java
branchJDK-8188051-branch
changeset 56380 f06946e00a26
parent 56373 1f76a5f8e999
child 56381 653b066f4a88
equal deleted inserted replaced
56373:1f76a5f8e999 56380:f06946e00a26
     1 /*
       
     2  * Copyright (c)  2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package java.sql2;
       
    26 
       
    27 import java.time.Duration;
       
    28 import java.util.concurrent.CompletionStage;
       
    29 import java.util.concurrent.Flow;
       
    30 import java.util.logging.Logger;
       
    31 import java.util.stream.Collector;
       
    32 
       
    33 /**
       
    34  * A set of {@link Operation}s that share certain properties, are managed as a
       
    35  * unit, and are executed as a unit. The {@link Operation}s created by an
       
    36  * {@link OperationGroup} and submitted are the member {@link Operation}s of
       
    37  * that {@link OperationGroup}.
       
    38  *
       
    39  * An {@link OperationGroup} conceptually has a collection of member
       
    40  * {@link Operation}s. When an {@link OperationGroup} is submitted it is placed
       
    41  * in the collection of the {@link OperationGroup} of which it is a member. The
       
    42  * member {@link OperationGroup} is executed according to the attributes of the
       
    43  * {@link OperationGroup} of which it is a member. The member {@link Operation}s
       
    44  * of an {@link OperationGroup} are executed according to the attributes of that
       
    45  * {@link OperationGroup}.
       
    46  *
       
    47  * How an {@link OperationGroup} is executed depends on its attributes.
       
    48  *
       
    49  * If an {@link OperationGroup} has a condition and the value of that condition
       
    50  * is {@link Boolean#TRUE} then execute the member {@link Operation}s as below.
       
    51  * If it is {@link Boolean#FALSE} then the {@link OperationGroup} is completed
       
    52  * with the value null. If the condition completed exceptionally then the
       
    53  * {@link OperationGroup} is completed exceptionally with a
       
    54  * {@link SqlSkippedException} that has that exception as its cause.
       
    55  *
       
    56  * If the {@link OperationGroup} is sequential the member {@link Operation}s are
       
    57  * executed in the order they were submitted. If it is parallel, they may be
       
    58  * executed in any order including simultaneously.
       
    59  *
       
    60  * If an {@link OperationGroup} is dependent and a member {@link Operation}
       
    61  * completes exceptionally the remaining member {@link Operation}s in the
       
    62  * collection are completed exceptionally with a {@link SqlSkippedException}
       
    63  * that has the initial {@link Exception} as its cause. A member
       
    64  * {@link Operation} in-flight may either complete normally or be completed
       
    65  * exceptionally but must complete one way or the other. [NOTE: Too strong?]
       
    66  *
       
    67  * If an {@link OperationGroup} is held additional member {@link Operation}s may
       
    68  * be submitted after the {@link OperationGroup} is submitted. If an
       
    69  * {@link OperationGroup} is not held, no additional member {@link Operation}s
       
    70  * may be submitted after the {@link OperationGroup} is submitted. If an
       
    71  * {@link OperationGroup} is held it will be completed only after it is released
       
    72  * or if conditional and the condition is not {@link Boolean#TRUE}. If a
       
    73  * {@link OperationGroup} is dependent, held, one of its member
       
    74  * {@link Operation}s completed exceptionally, and its queue is empty then the
       
    75  * {@link OperationGroup} is released.
       
    76  *
       
    77  * ISSUE: Currently no way to create a nested {@link OperationGroup}. That is a
       
    78  * intentional limitation but may be a simplification we can live with. Or not.
       
    79  *
       
    80  * @param <S> The type of the result of the member {@link Operation}s
       
    81  * @param <T> The type of the collected results the member
       
    82  * {@link Operation}s
       
    83  */
       
    84 public interface OperationGroup<S, T> extends Operation<T> {
       
    85 
       
    86   /**
       
    87    * Mark this {@link OperationGroup} as parallel. If this method is not called
       
    88    * the {@link OperationGroup} is sequential. If an {@link OperationGroup} is
       
    89    * parallel, member {@link Operation}s may be executed in any order including
       
    90    * in parallel. If an {@link OperationGroup} is sequential, the default,
       
    91    * member {@link Operation}s are executed strictly in the order they are
       
    92    * submitted.
       
    93    *
       
    94    * Note: There is no covariant override of this method in {@link Connection}
       
    95    * as there is only a small likelihood of needing it.
       
    96    *
       
    97    * @return this {@link OperationGroup}
       
    98    * @throws IllegalStateException if this method has been submitted or any
       
    99    * member {@link Operation}s have been created.
       
   100    */
       
   101   public OperationGroup<S, T> parallel();
       
   102 
       
   103   /**
       
   104    * Mark this {@link OperationGroup} as independent. If this method is not
       
   105    * called the {@link OperationGroup} is dependent, the default. If an
       
   106    * {@link OperationGroup} is independent then failure of one member
       
   107    * {@link Operation} does not affect the execution of other member
       
   108    * {@link Operation}s. If an {@link OperationGroup} is dependent then failure
       
   109    * of one member {@link Operation} will cause all member {@link Operation}s
       
   110    * remaining in the queue to be completed exceptionally with a
       
   111    * {@link SqlSkippedException} with the cause set to the original exception.
       
   112    *
       
   113    * Note: There is no covariant override of this method in {@link Connection}
       
   114    * as there is only a small likelihood of needing it.
       
   115    *
       
   116    * @return this {@link OperationGroup}
       
   117    * @throws IllegalStateException if this {@link OperationGroup} has been
       
   118    * submitted or any member {@link Operation}s have been created
       
   119    */
       
   120   public OperationGroup<S, T> independent();
       
   121 
       
   122   /**
       
   123    * Define a condition that determines whether the member {@link Operation}s of
       
   124    * this {@link OperationGroup} are executed or not. If and when this
       
   125    * {@link OperationGroup} is executed then if the condition argument is
       
   126    * completed with {@link Boolean#TRUE} the member {@link Operation}s are
       
   127    * executed. If {@link Boolean#FALSE} or if it is completed exceptionally the
       
   128    * member {@link Operation}s are not executed but are removed from the queue.
       
   129    * After all member {@link Operation}s have been removed from the queue this
       
   130    * {@link OperationGroup} is completed with {@code null}.
       
   131    *
       
   132    * Note: There is no covariant override of this method in Connection as there
       
   133    * is only a small likelihood of needing it.
       
   134    *
       
   135    * ISSUE: Should the member Operations be skipped or otherwise completed
       
   136    * exceptionally?
       
   137    *
       
   138    * @param condition a {@link CompletionStage} the value of which determines whether
       
   139    * this {@link OperationGroup} is executed or not
       
   140    * @return this OperationGroup
       
   141    * @throws IllegalStateException if this {@link OperationGroup} has been
       
   142    * submitted or any member {@link Operation}s have been created
       
   143    */
       
   144   public OperationGroup<S, T> conditional(CompletionStage<Boolean> condition);
       
   145 
       
   146   /**
       
   147    * Mark this {@link OperationGroup} as held. It can be executed but cannot be
       
   148    * completed. A {@link OperationGroup} that is held remains in the queue even
       
   149    * if all of its current member {@link Operation}s have completed. So long as
       
   150    * the {@link OperationGroup} is held new member {@link Operation}s can be
       
   151    * submitted. A {@link OperationGroup} that is held must be released before it
       
   152    * can be completed and removed from the queue.
       
   153    *
       
   154    * Note: There is no covariant override of this method in Connection as there
       
   155    * is only a small likelihood of needing it.
       
   156    *
       
   157    * ISSUE: Need a better name.
       
   158    *
       
   159    * @return this OperationGroup
       
   160    * @throws IllegalStateException if this {@link OperationGroup} has been
       
   161    * submitted
       
   162    */
       
   163   public OperationGroup<S, T> holdForMoreMembers();
       
   164 
       
   165   /**
       
   166    * Allow this {@link OperationGroup} to be completed and removed from the
       
   167    * queue once all of its member {@link Operation}s have been completed. After
       
   168    * this method is called no additional member {@link Operation}s can be
       
   169    * submitted. Once all member {@link Operation}s have been removed from the
       
   170    * queue this {@link OperationGroup} will be completed and removed from the
       
   171    * queue.
       
   172    *
       
   173    * Calling this method when this {@link OperationGroup} is not held is a noop.
       
   174    *
       
   175    * Note: There is no covariant override of this method in Connection as there
       
   176    * is only a small likelihood of needing it.
       
   177    *
       
   178    * ISSUE: Need a better name.
       
   179    *
       
   180    * @return this OperationGroup
       
   181    * @throws IllegalStateException if this {@link OperationGroup} has been
       
   182    * completed
       
   183    */
       
   184   public OperationGroup<S, T> releaseProhibitingMoreMembers();
       
   185 
       
   186   /**
       
   187    * Provides a {@link Collector} to reduce the results of the member
       
   188    * {@link Operation}s.The result of this {@link OperationGroup} is the result
       
   189    * of calling finisher on the final accumulated result. If the
       
   190    * {@link Collector} is {@link Collector.Characteristics#UNORDERED} the member
       
   191    * {@link Operation} results may be accumulated out of order. If the
       
   192    * {@link Collector} is {@link Collector.Characteristics#CONCURRENT} then the
       
   193    * member {@link Operation} results may be split into subsets that are reduced
       
   194    * separately and then combined. If this {@link OperationGroup} is sequential,
       
   195    * the characteristics of the {@link Collector} only affect how the results of
       
   196    * the member {@link Operation}s are collected; the member {@link Operation}s
       
   197    * are executed sequentially regardless. If this {@link OperationGroup} is
       
   198    * parallel the characteristics of the {@link Collector} may influence the
       
   199    * execution order of the member {@link Operation}s.
       
   200    *
       
   201    * @param <A> the type of the accumulator
       
   202    * @param <S> the type of the final result
       
   203    * @param c the Collector. Not null.
       
   204    * @return This OperationGroup
       
   205    * @throws IllegalStateException if called more than once or if this
       
   206    * {@link OperationGroup} has been submitted
       
   207    */
       
   208   public <A, S extends T> RowOperation<T> collect(Collector<? super Result.Row, A, S> c);
       
   209 
       
   210   /**
       
   211    * Return a new {@link ArrayCountOperation}.
       
   212    * <p>
       
   213    * Usage Note: Frequently use of this method will require a type witness
       
   214    * to enable correct type inferencing.
       
   215    * <pre><code>
       
   216    *   conn.<b>&lt;List&lt;Integer&gt;&gt;</b>arrayCountOperation(sql)
       
   217    *     .set ...
       
   218    *     .collect ...
       
   219    *     .submit ...
       
   220    * </code></pre>
       
   221    * 
       
   222    * @param <R> the result type of the returned {@link ArrayCountOperation}
       
   223    * @param sql SQL to be executed. Must return an update count.
       
   224    * @return a new {@link ArrayCountOperation} that is a member of this 
       
   225    * {@link OperationGroup}
       
   226    */
       
   227   public <R extends S> ArrayCountOperation<R> arrayCountOperation(String sql);
       
   228 
       
   229   /**
       
   230    * Return a new {@link CountOperation}.
       
   231    *
       
   232    * @param <R> the result type of the returned {@link CountOperation}
       
   233    * @param sql SQL to be executed. Must return an update count.
       
   234    * @return an new {@link CountOperation} that is a member of this 
       
   235    * {@link OperationGroup}
       
   236    *
       
   237    */
       
   238   public <R extends S> ParameterizedCountOperation<R> countOperation(String sql);
       
   239 
       
   240   /**
       
   241    * Return a new {@link Operation} for a SQL that doesn't return any result,
       
   242    * for example DDL.
       
   243    *
       
   244    * @param sql SQL for the {@link Operation}.
       
   245    * @return a new {@link Operation} that is a member of this 
       
   246    * {@link OperationGroup}
       
   247    */
       
   248   public Operation<Void> operation(String sql);
       
   249 
       
   250   /**
       
   251    * Return a new {@link OutOperation}. The SQL must return a set of zero or
       
   252    * more out parameters or function results.
       
   253    *
       
   254    * @param <R> the result type of the returned {@link OutOperation}
       
   255    * @param sql SQL for the {@link Operation}. Must return zero or more out
       
   256    * parameters or function results.
       
   257    * @return a new {@link OutOperation} that is a member of this 
       
   258    * {@link OperationGroup}
       
   259    */
       
   260   public <R extends S> OutOperation<R> outOperation(String sql);
       
   261 
       
   262   /**
       
   263    * Return a {@link ParameterizedRowOperation}.
       
   264    *
       
   265    * @param <R> the type of the result of the returned {@link ParameterizedRowOperation}
       
   266    * @param sql SQL for the {@link Operation}. Must return a row sequence.
       
   267    * @return a new {@link ParameterizedRowOperation} that is a member of this 
       
   268    * {@link OperationGroup}
       
   269    */
       
   270   public <R extends S> ParameterizedRowOperation<R> rowOperation(String sql);
       
   271 
       
   272   /**
       
   273    * Return a {@link StaticMultiOperation}.
       
   274    *
       
   275    * @param <R> the type of the result of the returned 
       
   276    * {@link StaticMultiOperation}
       
   277    * @param sql SQL for the {@link Operation}
       
   278    * @return a new {@link StaticMultiOperation} that is a member of this 
       
   279    * {@link OperationGroup}
       
   280    */
       
   281   public <R extends S> StaticMultiOperation<R> staticMultiOperation(String sql);
       
   282   
       
   283   /**
       
   284    * Return a {@link DynamicMultiOperation}. Use this when the number and type
       
   285    * of the results is not knowable.
       
   286    *
       
   287    * @param <R> the type of the result of the returned 
       
   288    * {@link DynamicMultiOperation}
       
   289    * @param sql SQL for the {@link Operation}
       
   290    * @return a new {@link DynamicMultiOperation} that is a member of this
       
   291    * {@link OperationGroup}
       
   292    */
       
   293   public <R extends S> DynamicMultiOperation<R> dynamicMultiOperation(String sql);
       
   294 
       
   295   /**
       
   296    * Return an {@link Operation} that ends the database transaction.
       
   297    * The transaction is ended with a commit unless the {@link Transaction} has
       
   298    * been {@link Transaction#setRollbackOnly} in which
       
   299    * case the transaction is ended with a rollback.
       
   300    *
       
   301    * The type argument {@link S} of the containing {@link OperationGroup} must be
       
   302    * a supertype of {@link TransactionOutcome}.
       
   303    *
       
   304    * @param trans the Transaction that determines whether the Operation does a
       
   305    * database commit or a database rollback.
       
   306    * @return an {@link Operation} that will end the database transaction.
       
   307    * @throws IllegalStateException if this {@link OperationGroup} has been submitted and
       
   308    * is not held or is parallel.
       
   309    */
       
   310   public Operation<TransactionOutcome> endTransactionOperation(Transaction trans);
       
   311 
       
   312   /**
       
   313    * Convenience method that creates and submits a endTransaction {@link Operation}
       
   314    * that commits by default but can be set to rollback by calling 
       
   315    * {@link Transaction#setRollbackOnly}.
       
   316    * 
       
   317    * @param trans the Transaction that determines whether the Operation is a
       
   318    * database commit or a database rollback.
       
   319    * @return this {@link OperationGroup}
       
   320    * @throws IllegalStateException if this {@link OperationGroup} has been submitted and
       
   321    * is not held or is parallel.
       
   322    */
       
   323   public default OperationGroup<S, T> commitMaybeRollback(Transaction trans) {
       
   324     this.endTransactionOperation(trans).submit();
       
   325     return this;
       
   326   }
       
   327   
       
   328   /**
       
   329    * Return a {@link LocalOperation}.
       
   330    *
       
   331    * @return a LocalOperation
       
   332    * @throws IllegalStateException if this OperationGroup has been submitted and
       
   333    * is not held
       
   334    */
       
   335   public LocalOperation<T> localOperation();
       
   336   
       
   337   /**
       
   338    * Returns a Flow.Processor that subscribes to a sequence of Operations and
       
   339    * produces a sequence of corresponding Submissions. The Operations must be
       
   340    * members of this OperationGroup. Calling Subscription.onNext with any
       
   341    * Operation that is not a member of this OperationGroup, that is was not
       
   342    * created by calling one of the Operation factory methods on this
       
   343    * OperationGroup, will cause the Subscription to be canceled and call
       
   344    * Subscriber.onError with IllegalArgumentException. The method
       
   345    * Subscription.onNext will call submit on each Operation it is passed and
       
   346    * publish the resulting Submission. Since an Operation can only be submitted
       
   347    * once, submitting an Operation and calling onNext with that submitted
       
   348    * Operation will cause the Subscription to be canceled and Subscriber.onError
       
   349    * to be called with IllegalStateException. The Processor does not retain
       
   350    * Submissions to produce to a subsequently attached Subscriber.
       
   351    * 
       
   352    * If there is no Subscriber to the Processor, the Processor will request
       
   353    * Operations as appropriate. If there is a Subscriber to the Processor, the
       
   354    * Processor will request Operations no faster than the Subscriber requests
       
   355    * Submissions.
       
   356    *
       
   357    * Each call to this method returns a new Flow.processor. The Submissions
       
   358    * published to each Processor are exactly those generated by calling submit
       
   359    * on the Operations passed as arguments to onNext on the same Processor.
       
   360    * Calling this method while there is an active Processor will throw
       
   361    * IllegalStateException.
       
   362    *
       
   363    * Note: If any Operation is submitted directly, that is by calling submit
       
   364    * rather than passing it to onNext, the Submission returned by the submit
       
   365    * call will not be published.
       
   366    *
       
   367    * @return a Flow.Processor that accepts Operations and generates Submissions
       
   368    * @throws IllegalStateException if there is an active Processor
       
   369    */
       
   370   public Flow.Processor<Operation<T>, Submission<T>> operationProcessor();
       
   371 
       
   372   /**
       
   373    * Supply a {@link Logger} for the implementation of this
       
   374    * {@link OperationGroup} to use to log significant events. Exactly what
       
   375    * events are logged, at what Level the events are logged and with what
       
   376    * parameters is implementation dependent. All member {@link Operation}s of
       
   377    * this {@link OperationGroup} will use the same {@link Logger} except a
       
   378    * member {@link OperationGroup} that is supplied with a different
       
   379    * {@link Logger} uses that {@link Logger}.
       
   380    *
       
   381    * Supplying a {@link Logger} configured with a
       
   382    * {@link java.util.logging.MemoryHandler} with the
       
   383    * {@link java.util.logging.MemoryHandler#pushLevel} set to
       
   384    * {@link java.util.logging.Level#WARNING} will result in no log output in
       
   385    * normal operation. In the event of an error the actions leading up to the
       
   386    * error will be logged.
       
   387    *
       
   388    * Implementation Note: Implementations are encouraged to log the creation of
       
   389    * this {@link OperationGroup} set to {@link java.util.logging.Level#INFO}, the
       
   390    * creation of member {@link Operation}s at the
       
   391    * {@link java.util.logging.Level#CONFIG} level, and execution of member
       
   392    * {@link Operation}s at the {@link java.util.logging.Level#FINE} level.
       
   393    * Detailed information about the execution of member {@link Operation}s may
       
   394    * be logged at the {@link java.util.logging.Level#FINER} and
       
   395    * {@link java.util.logging.Level#FINEST} levels. Errors in the execution of
       
   396    * user code should be logged at the {@link java.util.logging.Level#WARNING}
       
   397    * Level. Errors in the implementation code should be logged at the
       
   398    * {@link java.util.logging.Level#SEVERE} Level.
       
   399    *
       
   400    * @param logger used by the implementation to log significant events
       
   401    * @return this {@link OperationGroup}
       
   402    */
       
   403   public OperationGroup<S, T> logger(Logger logger);
       
   404 
       
   405   @Override
       
   406   public OperationGroup<S, T> timeout(Duration minTime);
       
   407 }