src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/OperationGroup.java
branchJDK-8188051-branch
changeset 56997 c9cbac2979fb
parent 56832 4f7713e6a308
equal deleted inserted replaced
56832:4f7713e6a308 56997:c9cbac2979fb
    33 
    33 
    34 /**
    34 /**
    35  * <p>
    35  * <p>
    36  * A set of {@link Operation}s that share certain properties, are managed as a
    36  * A set of {@link Operation}s that share certain properties, are managed as a
    37  * unit, and are executed as a unit. The {@link Operation}s created by an
    37  * unit, and are executed as a unit. The {@link Operation}s created by an
    38  * {@link OperationGroup} and submitted are the member {@link Operation}s of
    38  * {@code OperationGroup} and submitted are the member {@link Operation}s of
    39  * that {@link OperationGroup}. An {@link OperationGroup} is not a transaction
    39  * that {@code OperationGroup}. An {@code OperationGroup} is not a transaction
    40  * and is not related to a transaction in any way.</p>
    40  * and is not related to a transaction in any way.</p>
    41  *
    41  *
    42  * <p>
    42  * <p>
    43  * An {@link OperationGroup} conceptually has a collection of member
    43  * An {@link OperationGroup} provides conditional execution, control of error
    44  * {@link Operation}s. When an {@link OperationGroup} is submitted it is placed
    44  * response, and control of execution order.</p>
    45  * in the collection of the {@link OperationGroup} of which it is a member. The
    45  *
    46  * member {@link OperationGroup} is executed according to the attributes of the
    46  * <p>
    47  * {@link OperationGroup} of which it is a member. The member {@link Operation}s
    47  * Execution of one or more {@link Operation}s may depend on the result of a
    48  * of an {@link OperationGroup} are executed according to the attributes of that
    48  * previous {@link Operation}. Depending on the result of that previous
    49  * {@link OperationGroup}.</p>
    49  * {@link Operation} some other {@link Operation}s perhaps should not be
    50  *
    50  * executed. For example consider an account withdrawal. If the amount to
    51  * <p>
    51  * withdraw exceeds the account balance the withdrawal {@link Operation}s should
    52  * How an {@link OperationGroup} is executed depends on its attributes.</p>
    52  * not be executed and an overdraft {@link Operation} should be executed
    53  *
    53  * instead. It would be possible for the user thread to wait for the balance
    54  * <p>
    54  * check {@link Operation} but that would block. Better would be to use the
    55  * If an {@link OperationGroup} has a condition and the value of that condition
    55  * {@link java.util.concurrent.CompletionStage} of the balance check
       
    56  * {@link Operation} and submit the appropriate {@link Operation} in a
       
    57  * subsequent stage. But this is a common pattern and it is better still to
       
    58  * encapsulate that pattern, which conditional {@link OperationGroup} does.</p>
       
    59  *
       
    60  * <p>
       
    61  * Not all {@link Operation}s need to be executed in the order submitted. The
       
    62  * most common example is a mass insert. The order in which the records are
       
    63  * inserted doesn’t matter. A parallel {@link OperationGroup} gives the
       
    64  * implementation the freedom to execute the {@link Operation}s in any order. If
       
    65  * some of the {@link Operation}s have
       
    66  * {@link java.util.concurrent.CompletionStage} parameters this can be
       
    67  * especially valuable.</p>
       
    68  *
       
    69  * <p>
       
    70  * {@link OperationGroup} also allows control of error response. By default if
       
    71  * one {@link Operation} fails all subsequent {@link Operation}s are skipped.
       
    72  * That’s not always right. Consider the mass insert case. Just because one
       
    73  * insert fails doesn’t mean they should all fail. An independent
       
    74  * {@link OperationGroup} does this; the failure of one {@link Operation} has no
       
    75  * impact on the execution of the rest.</p>
       
    76  *
       
    77  * <p>
       
    78  * As an {@link OperationGroup} is an {@link Operation} it must be submitted
       
    79  * before its member {@link Operation}s are executed. Submitting an {@link OperationGroup}
       
    80  * allows its member {@link Operation}s to be executed but does not prohibit more
       
    81  * member {@link Operation}s from being submitted. Member {@link Operation}s may be 
       
    82  * submitted before and after the containing {@link OperationGroup} is submitted.</p>
       
    83  *
       
    84  * <p>
       
    85  * The result of an {@link OperationGroup} depends on the results of its member
       
    86  * {@link Operation}s. Therefore an {@link OperationGroup} must know when all
       
    87  * member {@link Operation}s have been submitted. It cannot generate a
       
    88  * result until all member {@link Operation}s are completed. Since member {@link Operation}s can be
       
    89  * submitted after the {@link OperationGroup} has been submitted (see previous
       
    90  * paragraph) submitting the containing {@link OperationGroup} is not sufficient to mark that all member
       
    91  * {@link Operation}s have been submitted. Calling {@link OperationGroup#close} signals
       
    92  * that all member Operations have been submitted. After close is called, no
       
    93  * more member Operations may be submitted and the OperationGroup will complete 
       
    94  * when all member Operations are complete.</p>
       
    95  * 
       
    96  * <p>
       
    97  * An {@code OperationGroup} conceptually has a collection of member
       
    98  * {@link Operation}s. When an {@code OperationGroup} is submitted it is placed
       
    99  * in the collection of the {@code OperationGroup} of which it is a member. The
       
   100  * member {@code OperationGroup} is executed according to the attributes of the
       
   101  * {@code OperationGroup} of which it is a member. The member {@link Operation}s
       
   102  * of an {@code OperationGroup} are executed according to the attributes of that
       
   103  * {@code OperationGroup}.</p>
       
   104  *
       
   105  * <p>
       
   106  * How an {@code OperationGroup} is executed depends on its attributes.</p>
       
   107  *
       
   108  * <p>
       
   109  * If an {@code OperationGroup} has a condition and the value of that condition
    56  * is {@link Boolean#TRUE} then execute the member {@link Operation}s as below.
   110  * is {@link Boolean#TRUE} then execute the member {@link Operation}s as below.
    57  * If it is {@link Boolean#FALSE} then the {@link OperationGroup} is completed
   111  * If it is {@link Boolean#FALSE} then the {@code OperationGroup} is completed
    58  * with the value null. If the condition completed exceptionally then the
   112  * with the value null. If the condition completed exceptionally then the
    59  * {@link OperationGroup} is completed exceptionally with a
   113  * {@code OperationGroup} is completed exceptionally with a
    60  * {@link SqlSkippedException} that has that exception as its cause.</p>
   114  * {@link SqlSkippedException} that has that exception as its cause.</p>
    61  * 
   115  *
    62  * <p>
   116  * <p>
    63  * If the {@link OperationGroup} is sequential the member {@link Operation}s are
   117  * If the {@code OperationGroup} is sequential the member {@link Operation}s are
    64  * executed in the order they were submitted. If it is parallel, they may be
   118  * executed in the order they were submitted. If it is parallel, they may be
    65  * executed in any order including simultaneously.</p>
   119  * executed in any order including simultaneously.</p>
    66  *
   120  *
    67  * <p>
   121  * <p>
    68  * If an {@link OperationGroup} is dependent and a member {@link Operation}
   122  * If an {@code OperationGroup} is dependent and a member {@link Operation}
    69  * completes exceptionally the remaining member {@link Operation}s in the
   123  * completes exceptionally the remaining member {@link Operation}s in the
    70  * collection are completed exceptionally with a {@link SqlSkippedException}
   124  * collection are completed exceptionally with a {@link SqlSkippedException}
    71  * that has the initial {@link Exception} as its cause and the {@link OperationGroup}
   125  * that has the initial {@link Exception} as its cause and the
    72  * is completed exceptionally with the initial {@link Exception}. A member
   126  * {@code OperationGroup} is completed exceptionally with the initial
    73  * {@link Operation} in-flight may either complete normally or be completed
   127  * {@link Exception}. A member {@link Operation} in-flight may either complete
    74  * exceptionally but must complete one way or the other. [NOTE: Too strong?]</p>
   128  * normally or be completed exceptionally but must complete one way or the
    75  *
   129  * other. [NOTE: Too strong?]</p>
    76  * <p>
   130  *
    77  * After a call to {@link OperationGroup#submitHoldingForMoreMembers} the
   131  * <p>
    78  * {@link OperationGroup} is submitted and held. After a call to 
   132  * The result of this {@code OperationGroup} is the result of collecting the
    79  * {@link OperationGroup#releaseProhibitingMoreMembers} the {@link OperationGroup} 
   133  * results of its member {@link Operation}s. If the {@code OperationGroup} is
    80  * is no longer held and is still submitted. Holding permits member {@link Operation}s
       
    81  * to be executed at the same time additional member {@link Operation}s are
       
    82  * submitted. Collecting the member {@link Operation}s' results does not begin
       
    83  * until the {@link OperationGroup} is no longer held.</p>
       
    84  * 
       
    85  * <p>
       
    86  * If an {@link OperationGroup} is held additional member {@link Operation}s may
       
    87  * be submitted. If an {@link OperationGroup} is not held, no additional member 
       
    88  * {@link Operation}s  may be submitted after the {@link OperationGroup} is 
       
    89  * submitted. If an {@link OperationGroup} is held it will be completed only after 
       
    90  * it is released or if conditional and the condition is not {@link Boolean#TRUE}. 
       
    91  * If a {@link OperationGroup} is dependent, held, one of its member
       
    92  * {@link Operation}s completed exceptionally, and its queue is empty then the
       
    93  * {@link OperationGroup} is released.</p>
       
    94  *
       
    95  * <p>
       
    96  * The result of this {@link OperationGroup} is the result of collecting the
       
    97  * results of its member {@link Operation}s. If the {@link OperationGroup} is 
       
    98  * dependent and one of its member {@link Operation}s completes exceptionally,
   134  * dependent and one of its member {@link Operation}s completes exceptionally,
    99  * the {@link OperationGroup} is completed exceptionally.</p>
   135  * the {@code OperationGroup} is completed exceptionally.</p>
   100  * 
   136  *
   101  * <p>
   137  * <p>
   102  * An implementation of this class must be thread safe as result and error
   138  * An implementation of this class must be thread safe as result and error
   103  * handlers running asynchronously may be accessing an {@link OperationGroup} in
   139  * handlers running asynchronously may be accessing an {@code OperationGroup} in
   104  * parallel with each other and with a user thread.</p>
   140  * parallel with each other and with a user thread.</p>
   105 
   141  *
   106 * <p>
   142 * <p>
   107  * ISSUE: Currently no way to create a nested {@link OperationGroup}. That is an
   143  * ISSUE: Currently no way to create a nested {@code OperationGroup}. That is an
   108  * intentional limitation but may be a simplification we can live with. Or not.</p>
   144  * intentional limitation but may be a simplification we can live with. Or
       
   145  * not.</p>
   109  *
   146  *
   110  * @param <S> The type of the result of the member {@link Operation}s
   147  * @param <S> The type of the result of the member {@link Operation}s
   111  * @param <T> The type of the collected results the member {@link Operation}s
   148  * @param <T> The type of the collected results the member {@link Operation}s
   112  */
   149  */
   113 public interface OperationGroup<S, T> extends Operation<T> {
   150 public interface OperationGroup<S, T> extends Operation<T>, AutoCloseable {
   114 
   151 
   115   /**
   152   /**
   116    * Mark this {@link OperationGroup} as parallel. If this method is not called
   153    * Mark this {@code OperationGroup} as parallel. If this method is not called
   117    * the {@link OperationGroup} is sequential. If an {@link OperationGroup} is
   154    * the {@code OperationGroup} is sequential. If an {@code OperationGroup} is
   118    * parallel, member {@link Operation}s may be executed in any order including
   155    * parallel, member {@link Operation}s may be executed in any order including
   119    * in parallel. If an {@link OperationGroup} is sequential, the default,
   156    * in parallel. If an {@code OperationGroup} is sequential, the default,
   120    * member {@link Operation}s are executed strictly in the order they are
   157    * member {@link Operation}s are executed strictly in the order they are
   121    * submitted.
   158    * submitted.
   122    *
   159    *
   123    * Note: There is no covariant override of this method in {@link Session}
   160    * Note: There is no covariant override of this method in {@link Session} as
   124    * as there is only a small likelihood of needing it.
   161    * there is only a small likelihood of needing it.
   125    *
   162    *
   126    * @return this {@link OperationGroup}
   163    * @return this {@code OperationGroup}
   127    * @throws IllegalStateException if this {@link OperationGroup} has been
   164    * @throws IllegalStateException if this {@code OperationGroup} has been
   128    * submitted, any member {@link Operation}s have been created, or this method
   165    * submitted, any member {@link Operation}s have been created, or this method
   129    * has been called previously
   166    * has been called previously
   130    */
   167    */
   131   public OperationGroup<S, T> parallel();
   168   public OperationGroup<S, T> parallel();
   132 
   169 
   133   /**
   170   /**
   134    * Mark this {@link OperationGroup} as independent. If this method is not
   171    * Mark this {@code OperationGroup} as independent. If this method is not
   135    * called the {@link OperationGroup} is dependent, the default. If an
   172    * called the {@code OperationGroup} is dependent, the default. If an
   136    * {@link OperationGroup} is independent then failure of one member
   173    * {@code OperationGroup} is independent then failure of one member
   137    * {@link Operation} does not affect the execution of other member
   174    * {@link Operation} does not affect the execution of other member
   138    * {@link Operation}s. If an {@link OperationGroup} is dependent then failure
   175    * {@link Operation}s. If an {@code OperationGroup} is dependent then failure
   139    * of one member {@link Operation} will cause all member {@link Operation}s
   176    * of one member {@link Operation} will cause all member {@link Operation}s
   140    * remaining in the queue to be completed exceptionally with a
   177    * remaining in the queue to be completed exceptionally with a
   141    * {@link SqlSkippedException} with the cause set to the original exception.
   178    * {@link SqlSkippedException} with the cause set to the original exception.
   142    *
   179    *
   143    * The result of this {@link OperationGroup}'s execution is the result of collecting the
   180    * The result of this {@code OperationGroup}'s execution is the result of
   144    * results of the member {@link Operation}s that complete normally. 
   181    * collecting the results of the member {@link Operation}s that complete
   145    *
   182    * normally.
   146    * Note: There is no covariant override of this method in {@link Session}
   183    *
   147    * as there is only a small likelihood of needing it.
   184    * Note: There is no covariant override of this method in {@link Session} as
   148    *
   185    * there is only a small likelihood of needing it.
   149    * @return this {@link OperationGroup}
   186    *
   150    * @throws IllegalStateException if this {@link OperationGroup} has been 
   187    * @return this {@code OperationGroup}
       
   188    * @throws IllegalStateException if this {@code OperationGroup} has been
   151    * submitted, any member {@link Operation}s have been created, or this method
   189    * submitted, any member {@link Operation}s have been created, or this method
   152    * has been called previously
   190    * has been called previously
   153    */
   191    */
   154   public OperationGroup<S, T> independent();
   192   public OperationGroup<S, T> independent();
   155 
   193 
   156   /**
   194   /**
   157    * Define a condition that determines whether the member {@link Operation}s of
   195    * Define a condition that determines whether the member {@link Operation}s of
   158    * this {@link OperationGroup} are executed or not. If and when this
   196    * this {@code OperationGroup} are executed or not. If and when this
   159    * {@link OperationGroup} is executed then if the condition argument is
   197    * {@code OperationGroup} is executed then if the condition argument is
   160    * completed with {@link Boolean#TRUE} the member {@link Operation}s are
   198    * completed with {@link Boolean#TRUE} the member {@link Operation}s are
   161    * executed. If {@link Boolean#FALSE} or if it is completed exceptionally the
   199    * executed. If {@link Boolean#FALSE} or if it is completed exceptionally the
   162    * member {@link Operation}s are not executed but are removed from the queue.
   200    * member {@link Operation}s are not executed but are removed from the queue.
   163    * After all member {@link Operation}s have been removed from the queue this
   201    * After all member {@link Operation}s have been removed from the queue this
   164    * {@link OperationGroup} is completed with {@code null}.
   202    * {@code OperationGroup} is completed with {@code null}.
   165    *
   203    *
   166    * Note: There is no covariant override of this method in Session as there
   204    * Note: There is no covariant override of this method in Session as there is
   167    * is only a small likelihood of needing it.
   205    * only a small likelihood of needing it.
   168    *
   206    *
   169    * ISSUE: Should the member Operations be skipped or otherwise completed
   207    * ISSUE: Should the member Operations be skipped or otherwise completed
   170    * exceptionally?
   208    * exceptionally?
   171    *
   209    *
   172    * @param condition a {@link CompletionStage} the value of which determines
   210    * @param condition a {@link CompletionStage} the value of which determines
   173    * whether this {@link OperationGroup} is executed or not
   211    * whether this {@code OperationGroup} is executed or not
   174    * @return this OperationGroup
   212    * @return this OperationGroup
   175    * @throws IllegalStateException if this {@link OperationGroup} has been
   213    * @throws IllegalStateException if this {@code OperationGroup} has been
   176    * submitted, any member {@link Operation}s have been created, or this method
   214    * submitted, any member {@link Operation}s have been created, or this method
   177    * has been called previously
   215    * has been called previously
   178    */
   216    */
   179   public OperationGroup<S, T> conditional(CompletionStage<Boolean> condition);
   217   public OperationGroup<S, T> conditional(CompletionStage<Boolean> condition);
   180 
   218 
   181   /**
   219   /**
   182    * Mark this {@link OperationGroup} as submitted and held. It can be executed but cannot be
       
   183    * completed. A {@link OperationGroup} that is held remains in the queue even
       
   184    * if all of its current member {@link Operation}s have completed. So long as
       
   185    * the {@link OperationGroup} is held new member {@link Operation}s can be
       
   186    * submitted. A {@link OperationGroup} that is held must be released before it
       
   187    * can be completed and removed from the queue.
       
   188    * 
       
   189    * If the {@link OperationGroup} is dependent and one of its member {@link Operation}s
       
   190    * completes exceptionally and its queue is empty the {@link OperationGroup}
       
   191    * is completed.
       
   192    *
       
   193    * Note: There is no covariant override of this method in Session as there
       
   194    * is only a small likelihood of needing it.
       
   195    *
       
   196    * ISSUE: Need a better name.
       
   197    *
       
   198    * @return a Submission for this OperationGroup
       
   199    * @throws IllegalStateException if this {@link OperationGroup} has been
       
   200    * submitted
       
   201    */
       
   202   public Submission<T> submitHoldingForMoreMembers();
       
   203 
       
   204   /**
       
   205    * Allow this {@link OperationGroup} to be completed and removed from the
       
   206    * queue once all of its member {@link Operation}s have been completed. After
       
   207    * this method is called no additional member {@link Operation}s can be
       
   208    * submitted. Once all member {@link Operation}s have been removed from the
       
   209    * queue this {@link OperationGroup} will be completed and removed from the
       
   210    * queue.
       
   211    *
       
   212    * Note: There is no covariant override of this method in Session as there
       
   213    * is only a small likelihood of needing it.
       
   214    *
       
   215    * ISSUE: Need a better name.
       
   216    *
       
   217    * @return the same Submission that was returned by {@link OperationGroup#submitHoldingForMoreMembers}
       
   218    * @throws IllegalStateException if this {@link OperationGroup} has been
       
   219    * completed or is not held.
       
   220    */
       
   221   public Submission<T> releaseProhibitingMoreMembers();
       
   222 
       
   223   /**
       
   224    * Provides a {@link Collector} to reduce the results of the member
   220    * Provides a {@link Collector} to reduce the results of the member
   225    * {@link Operation}s. The result of this {@link OperationGroup} is the result
   221    * {@link Operation}s. The result of this {@code OperationGroup} is the result
   226    * of calling finisher on the final accumulated result.If the
   222    * of calling finisher on the final accumulated result.If the
   227    * {@link Collector} is {@link Collector.Characteristics#UNORDERED} the member
   223    * {@link Collector} is {@link Collector.Characteristics#UNORDERED} the member
   228    * {@link Operation} results may be accumulated out of order.If the
   224    * {@link Operation} results may be accumulated out of order.If the
   229    * {@link Collector} is {@link Collector.Characteristics#CONCURRENT} then the
   225    * {@link Collector} is {@link Collector.Characteristics#CONCURRENT} then the
   230    * member {@link Operation} results may be split into subsets that are reduced
   226    * member {@link Operation} results may be split into subsets that are reduced
   231    * separately and then combined. If this {@link OperationGroup} is sequential,
   227    * separately and then combined. If this {@code OperationGroup} is sequential,
   232    * the characteristics of the {@link Collector} only affect how the results of
   228    * the characteristics of the {@link Collector} only affect how the results of
   233    * the member {@link Operation}s are collected; the member {@link Operation}s
   229    * the member {@link Operation}s are collected; the member {@link Operation}s
   234    * are executed sequentially regardless. If this {@link OperationGroup} is
   230    * are executed sequentially regardless. If this {@code OperationGroup} is
   235    * parallel the characteristics of the {@link Collector} may influence the
   231    * parallel the characteristics of the {@link Collector} may influence the
   236    * execution order of the member {@link Operation}s.
   232    * execution order of the member {@link Operation}s.
   237    *
   233    *
   238    * The default value is
   234    * The default value is
   239    * {@code Collector.of(()->null, (a,t)->{}, (l,r)->null, a->null)}.
   235    * {@code Collector.of(()->null, (a,t)->{}, (l,r)->null, a->null)}.
   240    *
   236    *
   241    * @param c the Collector. Not null.
   237    * @param c the Collector. Not null.
   242    * @return This OperationGroup
   238    * @return This OperationGroup
   243    * @throws IllegalStateException if called more than once or if this
   239    * @throws IllegalStateException if called more than once or if this
   244    * {@link OperationGroup} has been submitted
   240    * {@code OperationGroup} has been submitted
   245    */
   241    */
   246   public OperationGroup<S, T> collect(Collector<S, ?, T> c);
   242   public OperationGroup<S, T> collect(Collector<S, ?, T> c);
   247   
   243 
   248   /**
   244   /**
   249    * Return a new member {@link PrimitiveOperation} that is never skipped.
   245    * Return a new member {@link PrimitiveOperation} that is never skipped.
   250    * Skipping of member {@link Operation}s stops with a catchOperation and the
   246    * Skipping of member {@link Operation}s stops with a catchOperation and the
   251    * subsequent {@link Operation} is executed normally. The value of a
   247    * subsequent {@link Operation} is executed normally. The value of a
   252    * catchOperation is always null. Since a catchOperation is never completed
   248    * catchOperation is always null. Since a catchOperation is never completed
   253    * exceptionally, it has no error handler or timeout.
   249    * exceptionally, it has no error handler or timeout.
   254    *
   250    *
   255    * @return an {@link PrimitiveOperation} that is never skipped;
   251    * @return an {@link PrimitiveOperation} that is never skipped;
   256    * @throws IllegalStateException if the {@link OperationGroup} has been
   252    * @throws IllegalStateException if this {@code OperationGroup} is closed
   257    * submitted and is not held or if the {@link OperationGroup} is parallel or
   253    * or if this {@code OperationGroup} is parallel or independent.
   258    * independent.
       
   259    */
   254    */
   260   public PrimitiveOperation<S> catchOperation();
   255   public PrimitiveOperation<S> catchOperation();
   261   
   256 
   262   /**
   257   /**
   263    * Creates and submits a catch Operation. Convenience method.
   258    * Creates and submits a catch Operation. Convenience method.
   264    *
   259    *
   265    * @return this OperationGroup
   260    * @return this OperationGroup
   266    * @throws IllegalStateException if the {@link OperationGroup} has been
   261    * @throws IllegalStateException if this {@code OperationGroup} is closed
   267    * submitted and is not held or if the {@link OperationGroup} is parallel or
   262    * or if this {@code OperationGroup} is parallel or independent.
   268    * independent.
       
   269    */
   263    */
   270   public default OperationGroup<S, T> catchErrors() {
   264   public default OperationGroup<S, T> catchErrors() {
   271     catchOperation().submit();
   265     catchOperation().submit();
   272     return this;
   266     return this;
   273   }
   267   }
   285    * </code></pre>
   279    * </code></pre>
   286    *
   280    *
   287    * @param <R> the result type of the returned {@link ArrayRowCountOperation}
   281    * @param <R> the result type of the returned {@link ArrayRowCountOperation}
   288    * @param sql SQL to be executed. Must return an update count.
   282    * @param sql SQL to be executed. Must return an update count.
   289    * @return a new {@link ArrayRowCountOperation} that is a member of this
   283    * @return a new {@link ArrayRowCountOperation} that is a member of this
   290    * {@link OperationGroup}
   284    * {@code OperationGroup}
   291    * @throws IllegalStateException if the {@link OperationGroup} has been
   285    * @throws IllegalStateException if this {@code OperationGroup} is closed.
   292    * submitted and is not held
       
   293    */
   286    */
   294   public <R extends S> ArrayRowCountOperation<R> arrayRowCountOperation(String sql);
   287   public <R extends S> ArrayRowCountOperation<R> arrayRowCountOperation(String sql);
   295 
   288 
   296   /**
   289   /**
   297    * Return a new {@link ParameterizedRowCountOperation}.
   290    * Return a new {@link ParameterizedRowCountOperation}.
   298    *
   291    *
   299    * @param <R> the result type of the returned {@link RowCountOperation}
   292    * @param <R> the result type of the returned {@link RowCountOperation}
   300    * @param sql SQL to be executed. Must return an update count.
   293    * @param sql SQL to be executed. Must return an update count.
   301    * @return an new {@link ParameterizedRowCountOperation} that is a member of this
   294    * @return an new {@link ParameterizedRowCountOperation} that is a member of
   302    * {@link OperationGroup}
   295    * this {@code OperationGroup}
   303    * @throws IllegalStateException if the {@link OperationGroup} has been
   296    * @throws IllegalStateException if this {@code OperationGroup} is closed.
   304    * submitted and is not held
       
   305    */
   297    */
   306   public <R extends S> ParameterizedRowCountOperation<R> rowCountOperation(String sql);
   298   public <R extends S> ParameterizedRowCountOperation<R> rowCountOperation(String sql);
   307 
   299 
   308   /**
   300   /**
   309    * Return a new {@link Operation} for a SQL that doesn't return any result,
   301    * Return a new {@link Operation} for a SQL that doesn't return any result,
   310    * for example DDL. The result of this Operation is always null.
   302    * for example DDL. The result of this Operation is always null.
   311    * 
   303    *
   312    * The result of the returned Operation must be Void but specifying that here
   304    * The result of the returned Operation must be Void but specifying that here
   313    * causes problems.
   305    * causes problems.
   314    *
   306    *
   315    * @param sql SQL for the {@link Operation}.
   307    * @param sql SQL for the {@link Operation}.
   316    * @return a new {@link Operation} that is a member of this
   308    * @return a new {@link Operation} that is a member of this
   317    * {@link OperationGroup}
   309    * {@code OperationGroup}
   318    * @throws IllegalStateException if the {@link OperationGroup} has been
   310    * @throws IllegalStateException if this {@code OperationGroup} is closed.
   319    * submitted and is not held
       
   320    */
   311    */
   321   public Operation<S> operation(String sql);
   312   public Operation<S> operation(String sql);
   322 
   313 
   323   /**
   314   /**
   324    * Return a new {@link OutOperation} that is a member {@link Operation} of this 
   315    * Return a new {@link OutOperation} that is a member {@link Operation} of
   325    * {@link OperationGroup}. The SQL must return a set of zero or more out 
   316    * this {@code OperationGroup}. The SQL must return a set of zero or more out
   326    * parameters or function results.
   317    * parameters or function results.
   327    *
   318    *
   328    * @param <R> the result type of the returned {@link OutOperation}
   319    * @param <R> the result type of the returned {@link OutOperation}
   329    * @param sql SQL for the {@link Operation}. Must return zero or more out
   320    * @param sql SQL for the {@link Operation}. Must return zero or more out
   330    * parameters or function results.
   321    * parameters or function results.
   331    * @return a new {@link OutOperation} that is a member of this
   322    * @return a new {@link OutOperation} that is a member of this
   332    * {@link OperationGroup}
   323    * {@code OperationGroup}
   333    * @throws IllegalStateException if the {@link OperationGroup} has been
   324    * @throws IllegalStateException if this {@code OperationGroup} is closed.
   334    * submitted and is not held
       
   335    */
   325    */
   336   public <R extends S> OutOperation<R> outOperation(String sql);
   326   public <R extends S> OutOperation<R> outOperation(String sql);
   337 
   327 
   338   /**
   328   /**
   339    * Return a new {@link ParameterizedRowOperation} that is a member 
   329    * Return a new {@link ParameterizedRowOperation} that is a member
   340    * {@link Operation} of this {@link OperationGroup}.
   330    * {@link Operation} of this {@code OperationGroup}.
   341    *
   331    *
   342    * @param <R> the type of the result of the returned
   332    * @param <R> the type of the result of the returned
   343    * {@link ParameterizedRowOperation}
   333    * {@link ParameterizedRowOperation}
   344    * @param sql SQL for the {@link Operation}. Must return a row sequence.
   334    * @param sql SQL for the {@link Operation}. Must return a row sequence.
   345    * @return a new {@link ParameterizedRowOperation} that is a member of this
   335    * @return a new {@link ParameterizedRowOperation} that is a member of this
   346    * {@link OperationGroup}
   336    * {@code OperationGroup}
   347    * @throws IllegalStateException if the {@link OperationGroup} has been
   337    * @throws IllegalStateException if this {@code OperationGroup} is closed.
   348    * submitted and is not held
       
   349    */
   338    */
   350   public <R extends S> ParameterizedRowOperation<R> rowOperation(String sql);
   339   public <R extends S> ParameterizedRowOperation<R> rowOperation(String sql);
   351 
   340 
   352   /**
   341   /**
   353    * Return a new {@link ParameterizedRowPublisherOperation} that is a member
   342    * Return a new {@link ParameterizedRowPublisherOperation} that is a member
   354    * {@link Operation} of this {@link OperationGroup}.
   343    * {@link Operation} of this {@code OperationGroup}.
   355    *
   344    *
   356    * @param <R> the type of the result of the returned
   345    * @param <R> the type of the result of the returned
   357    * {@link ParameterizedRowPublisherOperation}
   346    * {@link ParameterizedRowPublisherOperation}
   358    * @param sql SQL for the {@link Operation}. Must return a row sequence.
   347    * @param sql SQL for the {@link Operation}. Must return a row sequence.
   359    * @return a new {@link ParameterizedRowPublisherOperation} that is a member
   348    * @return a new {@link ParameterizedRowPublisherOperation} that is a member
   360    * of this {@link OperationGroup}
   349    * of this {@code OperationGroup}
   361    * @throws IllegalStateException if the {@link OperationGroup} has been
   350    * @throws IllegalStateException if this {@code OperationGroup} is closed.
   362    * submitted and is not held
       
   363    */
   351    */
   364   public <R extends S> ParameterizedRowPublisherOperation<R> rowPublisherOperation(String sql);
   352   public <R extends S> ParameterizedRowPublisherOperation<R> rowPublisherOperation(String sql);
   365 
   353 
   366   /**
   354   /**
   367    * Return a new {@link MultiOperation} that is a member 
   355    * Return a new {@link MultiOperation} that is a member {@link Operation} of
   368    * {@link Operation} of this {@link OperationGroup}.
   356    * this {@code OperationGroup}.
   369    *
   357    *
   370    * @param <R> the type of the result of the returned
   358    * @param <R> the type of the result of the returned {@link MultiOperation}
   371    * {@link MultiOperation}
       
   372    * @param sql SQL for the {@link Operation}
   359    * @param sql SQL for the {@link Operation}
   373    * @return a new {@link MultiOperation} that is a member of this
   360    * @return a new {@link MultiOperation} that is a member of this
   374    * {@link OperationGroup}
   361    * {@code OperationGroup}
   375    * @throws IllegalStateException if the {@link OperationGroup} has been
   362    * @throws IllegalStateException if this {@code OperationGroup} is closed.
   376    * submitted and is not held
       
   377    */
   363    */
   378   public <R extends S> MultiOperation<R> multiOperation(String sql);
   364   public <R extends S> MultiOperation<R> multiOperation(String sql);
   379 
   365 
   380   /**
   366   /**
   381    * Return a new {@link Operation} that ends the database transaction. This
   367    * Return a new {@link Operation} that ends the database transaction. This
   382    * {@link Operation} is a member of the {@link OperationGroup}. The
   368    * {@link Operation} is a member of the {@code OperationGroup}. The
   383    * transaction is ended with a commit unless the {@link TransactionCompletion}
   369    * transaction is ended with a commit unless the {@link TransactionCompletion}
   384    * has been {@link TransactionCompletion#setRollbackOnly} in which case the
   370    * has been {@link TransactionCompletion#setRollbackOnly} in which case the
   385    * transaction is ended with a rollback.
   371    * transaction is ended with a rollback.
   386    * 
   372    *
   387    * <p>
   373    * <p>
   388    * An endTransaction Operation may be skipped. To insure that it will not be
   374    * An endTransaction Operation may be skipped. To insure that it will not be
   389    * skipped it should immediately follow a catch Operation. All end transaction
   375    * skipped it should immediately follow a catch Operation. All end transaction
   390    * convenience methods do so.</p>
   376    * convenience methods do so.</p>
   391    *
   377    *
   392    * The type argument {@link S} of the containing {@link OperationGroup} must
   378    * The type argument {@link S} of the containing {@code OperationGroup} must
   393    * be a supertype of {@link TransactionOutcome}.
   379    * be a supertype of {@link TransactionOutcome}.
   394    *
   380    *
   395    * @param trans the TransactionCompletion that determines whether the Operation does a 
   381    * @param trans the TransactionCompletion that determines whether the
   396  database commit or a database rollback.
   382    * Operation does a database commit or a database rollback.
   397    * @return an {@link Operation} that will end the database transaction.
   383    * @return an {@link Operation} that will end the database transaction.
   398    * @throws IllegalStateException if this {@link OperationGroup} has been
   384    * @throws IllegalStateException if this {@code OperationGroup} is closed
   399    * submitted and is not held or is parallel.
   385    * or is parallel.
   400    */
   386    */
   401   public Operation<TransactionOutcome> endTransactionOperation(TransactionCompletion trans);
   387   public Operation<TransactionOutcome> endTransactionOperation(TransactionCompletion trans);
   402 
   388 
   403   /**
   389   /**
   404    * Convenience method that creates and submits a endTransaction
   390    * Convenience method that creates and submits a endTransaction
   405    * {@link Operation} that commits by default but can be set to rollback by
   391    * {@link Operation} that commits by default but can be set to rollback by
   406    * calling {@link TransactionCompletion#setRollbackOnly}. The endTransaction Operation
   392    * calling {@link TransactionCompletion#setRollbackOnly}. The endTransaction
   407    * is never skipped.
   393    * Operation is never skipped.
   408    *
   394    *
   409    * @param trans the TransactionCompletion that determines whether the {@link Operation} is a
   395    * @param trans the TransactionCompletion that determines whether the
   410    * database commit or a database rollback.
   396    * {@link Operation} is a database commit or a database rollback.
   411    * @return a {@link CompletionStage} that is completed with the outcome of the 
   397    * @return a {@link CompletionStage} that is completed with the outcome of the
   412    * transaction
   398    * transaction
   413    * @throws IllegalStateException if this {@link OperationGroup} has been
   399    * @throws IllegalStateException if this {@code OperationGroup} is closed
   414    * submitted and is not held or is parallel.
   400    * or is parallel.
   415    */
   401    */
   416   public default CompletionStage<TransactionOutcome> commitMaybeRollback(TransactionCompletion trans) {
   402   public default CompletionStage<TransactionOutcome> commitMaybeRollback(TransactionCompletion trans) {
   417     catchErrors();
   403     catchErrors();
   418     return this.endTransactionOperation(trans).submit().getCompletionStage();
   404     return this.endTransactionOperation(trans).submit().getCompletionStage();
   419   }
   405   }
   420 
   406 
   421   /**
   407   /**
   422    * Return a new {@link LocalOperation} that is a member {@link Operation} of 
   408    * Return a new {@link LocalOperation} that is a member {@link Operation} of
   423    * this {@link OperationGroup}.
   409    * this {@code OperationGroup}.
   424    *
   410    *
   425    * @param <R> value type of the returned local {@link Operation}
   411    * @param <R> value type of the returned local {@link Operation}
   426    * @return a LocalOperation
   412    * @return a LocalOperation
   427    * @throws IllegalStateException if this {@link OperationGroup} has been submitted and
   413    * @throws IllegalStateException if this {@code OperationGroup} is closed.
   428    * is not held
       
   429    */
   414    */
   430   public <R extends S> LocalOperation<R> localOperation();
   415   public <R extends S> LocalOperation<R> localOperation();
   431 
   416 
   432   /**
   417   /**
   433    * Supply a {@link Logger} for the implementation of this
   418    * Supply a {@link Logger} for the implementation of this
   434    * {@link OperationGroup} to use to log significant events. Exactly what
   419    * {@code OperationGroup} to use to log significant events. Exactly what
   435    * events are logged, at what Level the events are logged and with what
   420    * events are logged, at what Level the events are logged and with what
   436    * parameters is implementation dependent. All member {@link Operation}s of
   421    * parameters is implementation dependent. All member {@link Operation}s of
   437    * this {@link OperationGroup} will use the same {@link Logger} except a
   422    * this {@code OperationGroup} will use the same {@link Logger} except a
   438    * member {@link OperationGroup} that is supplied with a different
   423    * member {@code OperationGroup} that is supplied with a different
   439    * {@link Logger} uses that {@link Logger}.
   424    * {@link Logger} uses that {@link Logger}.
   440    *
   425    *
   441    * Supplying a {@link Logger} configured with a
   426    * Supplying a {@link Logger} configured with a
   442    * {@link java.util.logging.MemoryHandler} with the
   427    * {@link java.util.logging.MemoryHandler} with the
   443    * {@link java.util.logging.MemoryHandler#pushLevel} set to
   428    * {@link java.util.logging.MemoryHandler#pushLevel} set to
   444    * {@link java.util.logging.Level#WARNING} will result in no log output in
   429    * {@link java.util.logging.Level#WARNING} will result in no log output in
   445    * normal operation. In the event of an error the actions leading up to the
   430    * normal operation. In the event of an error the actions leading up to the
   446    * error will be logged.
   431    * error will be logged.
   447    *
   432    *
   448    * Implementation Note: Implementations are encouraged to log the creation of
   433    * Implementation Note: Implementations are encouraged to log the creation of
   449    * this {@link OperationGroup} set to {@link java.util.logging.Level#INFO},
   434    * this {@code OperationGroup} set to {@link java.util.logging.Level#INFO},
   450    * the creation of member {@link Operation}s at the
   435    * the creation of member {@link Operation}s at the
   451    * {@link java.util.logging.Level#CONFIG} level, and execution of member
   436    * {@link java.util.logging.Level#CONFIG} level, and execution of member
   452    * {@link Operation}s at the {@link java.util.logging.Level#FINE} level.
   437    * {@link Operation}s at the {@link java.util.logging.Level#FINE} level.
   453    * Detailed information about the execution of member {@link Operation}s may
   438    * Detailed information about the execution of member {@link Operation}s may
   454    * be logged at the {@link java.util.logging.Level#FINER} and
   439    * be logged at the {@link java.util.logging.Level#FINER} and
   456    * user code should be logged at the {@link java.util.logging.Level#WARNING}
   441    * user code should be logged at the {@link java.util.logging.Level#WARNING}
   457    * Level. Errors in the implementation code should be logged at the
   442    * Level. Errors in the implementation code should be logged at the
   458    * {@link java.util.logging.Level#SEVERE} Level.
   443    * {@link java.util.logging.Level#SEVERE} Level.
   459    *
   444    *
   460    * @param logger used by the implementation to log significant events
   445    * @param logger used by the implementation to log significant events
   461    * @return this {@link OperationGroup}
   446    * @return this {@code OperationGroup}
   462    */
   447    */
   463   public OperationGroup<S, T> logger(Logger logger);
   448   public OperationGroup<S, T> logger(Logger logger);
   464 
   449 
   465   /**
   450   /**
   466    * Returns a {@code String} enclosed in single quotes. Any occurrence of a
   451    * Returns a {@code String} enclosed in single quotes. Any occurrence of a
   482    *
   467    *
   483    * </tbody>
   468    * </tbody>
   484    * </table>
   469    * </table>
   485    * </blockquote>
   470    * </blockquote>
   486    *
   471    *
   487    * @implNote JDBC driver implementations may need to provide their own
   472    * @implNote ADBA driver implementations may need to provide their own
   488    * implementation of this method in order to meet the requirements of the
   473    * implementation of this method in order to meet the requirements of the
   489    * underlying datasource.
   474    * underlying datasource.
   490    * @param val a character string. Not null
   475    * @param val a character string. Not null
   491    * @return A string enclosed by single quotes with every single quote
   476    * @return A string enclosed by single quotes with every single quote
   492    * converted to two single quotes. Not null
   477    * converted to two single quotes. Not null
   592    * @param identifier a SQL identifier. Not null
   577    * @param identifier a SQL identifier. Not null
   593    * @param alwaysQuote indicates if a simple SQL identifier should be returned
   578    * @param alwaysQuote indicates if a simple SQL identifier should be returned
   594    * as a quoted identifier
   579    * as a quoted identifier
   595    * @return A simple SQL identifier or a delimited identifier. Not null
   580    * @return A simple SQL identifier or a delimited identifier. Not null
   596    * @throws NullPointerException if identifier is {@code null}
   581    * @throws NullPointerException if identifier is {@code null}
   597    * @throws IllegalArgumentException if {@code identifier} can not be converted 
   582    * @throws IllegalArgumentException if {@code identifier} can not be converted
   598    * to a valid identifier
   583    * to a valid identifier
   599    */
   584    */
   600   default String enquoteIdentifier(String identifier, boolean alwaysQuote) {
   585   default String enquoteIdentifier(String identifier, boolean alwaysQuote) {
   601     int len = identifier.length();
   586     int len = identifier.length();
   602     if (len < 1 || len > 128) {
   587     if (len < 1 || len > 128) {
   721    */
   706    */
   722   default String enquoteNCharLiteral(String val) {
   707   default String enquoteNCharLiteral(String val) {
   723     return "N'" + val.replace("'", "''") + "'";
   708     return "N'" + val.replace("'", "''") + "'";
   724   }
   709   }
   725 
   710 
   726     // Covariant overrides
   711   /**
       
   712    * Allow this {@code OperationGroup} to be completed and removed from the
       
   713    * queue once all of its member {@link Operation}s have been completed. After
       
   714    * this method is called no additional member {@link Operation}s can be
       
   715    * submitted. Once all member {@link Operation}s have been removed from the
       
   716    * queue this {@code OperationGroup} will be completed and removed from the
       
   717    * queue.
       
   718    * 
       
   719    * {@inheritDoc}
       
   720    */
       
   721   @Override
       
   722   public void close();
       
   723 
       
   724   // Covariant overrides
       
   725   /**
       
   726    * {@inheritDoc}
       
   727    *
       
   728    * @return this {@code OperationGroup}
       
   729    */
   727   @Override
   730   @Override
   728   public OperationGroup<S, T> timeout(Duration minTime);
   731   public OperationGroup<S, T> timeout(Duration minTime);
   729 
   732 
       
   733   /**
       
   734    * {@inheritDoc}
       
   735    *
       
   736    * @return this {@code OperationGroup}
       
   737    */
   730   @Override
   738   @Override
   731   public OperationGroup<S, T> onError(Consumer<Throwable> handler);
   739   public OperationGroup<S, T> onError(Consumer<Throwable> handler);
   732   
   740 
   733 }
   741 }