-
- Type Parameters:
S
- The type of the result of the memberOperation
sT
- The type of the collected results the memberOperation
s
- All Superinterfaces:
java.lang.AutoCloseable
,Operation<T>
,PrimitiveOperation<T>
- All Known Subinterfaces:
Session
public interface OperationGroup<S,T> extends Operation<T>, java.lang.AutoCloseable
A set of
Operation
s that share certain properties, are managed as a unit, and are executed as a unit. TheOperation
s created by anOperationGroup
and submitted are the memberOperation
s of thatOperationGroup
. AnOperationGroup
is not a transaction and is not related to a transaction in any way.An
OperationGroup
provides conditional execution, control of error response, and control of execution order.Execution of one or more
Operation
s may depend on the result of a previousOperation
. Depending on the result of that previousOperation
some otherOperation
s perhaps should not be executed. For example consider an account withdrawal. If the amount to withdraw exceeds the account balance the withdrawalOperation
s should not be executed and an overdraftOperation
should be executed instead. It would be possible for the user thread to wait for the balance checkOperation
but that would block. Better would be to use theCompletionStage
of the balance checkOperation
and submit the appropriateOperation
in a subsequent stage. But this is a common pattern and it is better still to encapsulate that pattern, which conditionalOperationGroup
does.Not all
Operation
s need to be executed in the order submitted. The most common example is a mass insert. The order in which the records are inserted doesn’t matter. A parallelOperationGroup
gives the implementation the freedom to execute theOperation
s in any order. If some of theOperation
s haveCompletionStage
parameters this can be especially valuable.OperationGroup
also allows control of error response. By default if oneOperation
fails all subsequentOperation
s are skipped. That’s not always right. Consider the mass insert case. Just because one insert fails doesn’t mean they should all fail. An independentOperationGroup
does this; the failure of oneOperation
has no impact on the execution of the rest.As an
OperationGroup
is anOperation
it must be submitted before its memberOperation
s are executed. Submitting anOperationGroup
allows its memberOperation
s to be executed but does not prohibit more memberOperation
s from being submitted. MemberOperation
s may be submitted before and after the containingOperationGroup
is submitted.The result of an
OperationGroup
depends on the results of its memberOperation
s. Therefore anOperationGroup
must know when all memberOperation
s have been submitted. It cannot generate a result until all memberOperation
s are completed. Since memberOperation
s can be submitted after theOperationGroup
has been submitted (see previous paragraph) submitting the containingOperationGroup
is not sufficient to mark that all memberOperation
s have been submitted. Callingclose()
signals that all member Operations have been submitted. After close is called, no more member Operations may be submitted and the OperationGroup will complete when all member Operations are complete.An
OperationGroup
conceptually has a collection of memberOperation
s. When anOperationGroup
is submitted it is placed in the collection of theOperationGroup
of which it is a member. The memberOperationGroup
is executed according to the attributes of theOperationGroup
of which it is a member. The memberOperation
s of anOperationGroup
are executed according to the attributes of thatOperationGroup
.How an
OperationGroup
is executed depends on its attributes.If an
OperationGroup
has a condition and the value of that condition isBoolean.TRUE
then execute the memberOperation
s as below. If it isBoolean.FALSE
then theOperationGroup
is completed with the value null. If the condition completed exceptionally then theOperationGroup
is completed exceptionally with aSqlSkippedException
that has that exception as its cause.If the
OperationGroup
is sequential the memberOperation
s are executed in the order they were submitted. If it is parallel, they may be executed in any order including simultaneously.If an
OperationGroup
is dependent and a memberOperation
completes exceptionally the remaining memberOperation
s in the collection are completed exceptionally with aSqlSkippedException
that has the initialException
as its cause and theOperationGroup
is completed exceptionally with the initialException
. A memberOperation
in-flight may either complete normally or be completed exceptionally but must complete one way or the other. [NOTE: Too strong?]The result of this
OperationGroup
is the result of collecting the results of its memberOperation
s. If theOperationGroup
is dependent and one of its memberOperation
s completes exceptionally, theOperationGroup
is completed exceptionally.An implementation of this class must be thread safe as result and error handlers running asynchronously may be accessing an
OperationGroup
in parallel with each other and with a user thread.ISSUE: Currently no way to create a nested
OperationGroup
. That is an intentional limitation but may be a simplification we can live with. Or not.
-
-
Method Summary
All Methods Instance Methods Abstract Methods Default Methods Modifier and Type Method Description <R extends S>
ArrayRowCountOperation<R>arrayRowCountOperation(java.lang.String sql)
Return a newArrayRowCountOperation
.default OperationGroup<S,T>
catchErrors()
Creates and submits a catch Operation.PrimitiveOperation<S>
catchOperation()
Return a new memberPrimitiveOperation
that is never skipped.void
close()
Allow thisOperationGroup
to be completed and removed from the queue once all of its memberOperation
s have been completed.OperationGroup<S,T>
collect(java.util.stream.Collector<S,?,T> c)
Provides aCollector
to reduce the results of the memberOperation
s.default java.util.concurrent.CompletionStage<TransactionOutcome>
commitMaybeRollback(TransactionCompletion trans)
Convenience method that creates and submits a endTransactionOperation
that commits by default but can be set to rollback by callingTransactionCompletion.setRollbackOnly()
.OperationGroup<S,T>
conditional(java.util.concurrent.CompletionStage<java.lang.Boolean> condition)
Define a condition that determines whether the memberOperation
s of thisOperationGroup
are executed or not.Operation<TransactionOutcome>
endTransactionOperation(TransactionCompletion trans)
Return a newOperation
that ends the database transaction.default java.lang.String
enquoteIdentifier(java.lang.String identifier, boolean alwaysQuote)
Returns a SQL identifier.default java.lang.String
enquoteLiteral(java.lang.String val)
Returns aString
enclosed in single quotes.default java.lang.String
enquoteNCharLiteral(java.lang.String val)
Returns aString
representing a National Character Set Literal enclosed in single quotes and prefixed with a upper case letter N.OperationGroup<S,T>
independent()
Mark thisOperationGroup
as independent.default boolean
isSimpleIdentifier(java.lang.String identifier)
Retrieves whetheridentifier
is a simple SQL identifier.<R extends S>
LocalOperation<R>localOperation()
OperationGroup<S,T>
logger(java.util.logging.Logger logger)
Supply aLogger
for the implementation of thisOperationGroup
to use to log significant events.<R extends S>
MultiOperation<R>multiOperation(java.lang.String sql)
OperationGroup<S,T>
onError(java.util.function.Consumer<java.lang.Throwable> handler)
Provides an error handler for thisOperation
.Operation<S>
operation(java.lang.String sql)
Return a newOperation
for a SQL that doesn't return any result, for example DDL.<R extends S>
OutOperation<R>outOperation(java.lang.String sql)
OperationGroup<S,T>
parallel()
Mark thisOperationGroup
as parallel.<R extends S>
ParameterizedRowCountOperation<R>rowCountOperation(java.lang.String sql)
Return a newParameterizedRowCountOperation
.<R extends S>
ParameterizedRowOperation<R>rowOperation(java.lang.String sql)
<R extends S>
ParameterizedRowPublisherOperation<R>rowPublisherOperation(java.lang.String sql)
OperationGroup<S,T>
timeout(java.time.Duration minTime)
The minimum time before thisOperation
might be canceled automatically.-
Methods inherited from interface jdk.incubator.sql2.PrimitiveOperation
submit
-
-
-
-
Method Detail
-
parallel
OperationGroup<S,T> parallel()
Mark thisOperationGroup
as parallel. If this method is not called theOperationGroup
is sequential. If anOperationGroup
is parallel, memberOperation
s may be executed in any order including in parallel. If anOperationGroup
is sequential, the default, memberOperation
s are executed strictly in the order they are submitted. Note: There is no covariant override of this method inSession
as there is only a small likelihood of needing it.- Returns:
- this
OperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
has been submitted, any memberOperation
s have been created, or this method has been called previously
-
independent
OperationGroup<S,T> independent()
Mark thisOperationGroup
as independent. If this method is not called theOperationGroup
is dependent, the default. If anOperationGroup
is independent then failure of one memberOperation
does not affect the execution of other memberOperation
s. If anOperationGroup
is dependent then failure of one memberOperation
will cause all memberOperation
s remaining in the queue to be completed exceptionally with aSqlSkippedException
with the cause set to the original exception. The result of thisOperationGroup
's execution is the result of collecting the results of the memberOperation
s that complete normally. Note: There is no covariant override of this method inSession
as there is only a small likelihood of needing it.- Returns:
- this
OperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
has been submitted, any memberOperation
s have been created, or this method has been called previously
-
conditional
OperationGroup<S,T> conditional(java.util.concurrent.CompletionStage<java.lang.Boolean> condition)
Define a condition that determines whether the memberOperation
s of thisOperationGroup
are executed or not. If and when thisOperationGroup
is executed then if the condition argument is completed withBoolean.TRUE
the memberOperation
s are executed. IfBoolean.FALSE
or if it is completed exceptionally the memberOperation
s are not executed but are removed from the queue. After all memberOperation
s have been removed from the queue thisOperationGroup
is completed withnull
. Note: There is no covariant override of this method in Session as there is only a small likelihood of needing it. ISSUE: Should the member Operations be skipped or otherwise completed exceptionally?- Parameters:
condition
- aCompletionStage
the value of which determines whether thisOperationGroup
is executed or not- Returns:
- this OperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
has been submitted, any memberOperation
s have been created, or this method has been called previously
-
collect
OperationGroup<S,T> collect(java.util.stream.Collector<S,?,T> c)
Provides aCollector
to reduce the results of the memberOperation
s. The result of thisOperationGroup
is the result of calling finisher on the final accumulated result.If theCollector
isCollector.Characteristics.UNORDERED
the memberOperation
results may be accumulated out of order.If theCollector
isCollector.Characteristics.CONCURRENT
then the memberOperation
results may be split into subsets that are reduced separately and then combined. If thisOperationGroup
is sequential, the characteristics of theCollector
only affect how the results of the memberOperation
s are collected; the memberOperation
s are executed sequentially regardless. If thisOperationGroup
is parallel the characteristics of theCollector
may influence the execution order of the memberOperation
s. The default value isCollector.of(()->null, (a,t)->{}, (l,r)->null, a->null)
.- Parameters:
c
- the Collector. Not null.- Returns:
- This OperationGroup
- Throws:
java.lang.IllegalStateException
- if called more than once or if thisOperationGroup
has been submitted
-
catchOperation
PrimitiveOperation<S> catchOperation()
Return a new memberPrimitiveOperation
that is never skipped. Skipping of memberOperation
s stops with a catchOperation and the subsequentOperation
is executed normally. The value of a catchOperation is always null. Since a catchOperation is never completed exceptionally, it has no error handler or timeout.- Returns:
- an
PrimitiveOperation
that is never skipped; - Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed or if thisOperationGroup
is parallel or independent.
-
catchErrors
default OperationGroup<S,T> catchErrors()
Creates and submits a catch Operation. Convenience method.- Returns:
- this OperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed or if thisOperationGroup
is parallel or independent.
-
arrayRowCountOperation
<R extends S> ArrayRowCountOperation<R> arrayRowCountOperation(java.lang.String sql)
Return a newArrayRowCountOperation
.Usage Note: Frequently use of this method will require a type witness to enable correct type inferencing.
session.<List<Integer>>arrayCountOperation(sql) .set ... .collect ... .submit ...
- Type Parameters:
R
- the result type of the returnedArrayRowCountOperation
- Parameters:
sql
- SQL to be executed. Must return an update count.- Returns:
- a new
ArrayRowCountOperation
that is a member of thisOperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed.
-
rowCountOperation
<R extends S> ParameterizedRowCountOperation<R> rowCountOperation(java.lang.String sql)
Return a newParameterizedRowCountOperation
.- Type Parameters:
R
- the result type of the returnedRowCountOperation
- Parameters:
sql
- SQL to be executed. Must return an update count.- Returns:
- an new
ParameterizedRowCountOperation
that is a member of thisOperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed.
-
operation
Operation<S> operation(java.lang.String sql)
Return a newOperation
for a SQL that doesn't return any result, for example DDL. The result of this Operation is always null. The result of the returned Operation must be Void but specifying that here causes problems.
-
outOperation
<R extends S> OutOperation<R> outOperation(java.lang.String sql)
Return a newOutOperation
that is a memberOperation
of thisOperationGroup
. The SQL must return a set of zero or more out parameters or function results.- Type Parameters:
R
- the result type of the returnedOutOperation
- Parameters:
sql
- SQL for theOperation
. Must return zero or more out parameters or function results.- Returns:
- a new
OutOperation
that is a member of thisOperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed.
-
rowOperation
<R extends S> ParameterizedRowOperation<R> rowOperation(java.lang.String sql)
- Type Parameters:
R
- the type of the result of the returnedParameterizedRowOperation
- Parameters:
sql
- SQL for theOperation
. Must return a row sequence.- Returns:
- a new
ParameterizedRowOperation
that is a member of thisOperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed.
-
rowPublisherOperation
<R extends S> ParameterizedRowPublisherOperation<R> rowPublisherOperation(java.lang.String sql)
- Type Parameters:
R
- the type of the result of the returnedParameterizedRowPublisherOperation
- Parameters:
sql
- SQL for theOperation
. Must return a row sequence.- Returns:
- a new
ParameterizedRowPublisherOperation
that is a member of thisOperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed.
-
multiOperation
<R extends S> MultiOperation<R> multiOperation(java.lang.String sql)
- Type Parameters:
R
- the type of the result of the returnedMultiOperation
- Parameters:
sql
- SQL for theOperation
- Returns:
- a new
MultiOperation
that is a member of thisOperationGroup
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed.
-
endTransactionOperation
Operation<TransactionOutcome> endTransactionOperation(TransactionCompletion trans)
Return a newOperation
that ends the database transaction. ThisOperation
is a member of theOperationGroup
. The transaction is ended with a commit unless theTransactionCompletion
has beenTransactionCompletion.setRollbackOnly()
in which case the transaction is ended with a rollback.An endTransaction Operation may be skipped. To insure that it will not be skipped it should immediately follow a catch Operation. All end transaction convenience methods do so.
The type argumentOperationGroup
of the containingOperationGroup
must be a supertype ofTransactionOutcome
.- Parameters:
trans
- the TransactionCompletion that determines whether the Operation does a database commit or a database rollback.- Returns:
- an
Operation
that will end the database transaction. - Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed or is parallel.
-
commitMaybeRollback
default java.util.concurrent.CompletionStage<TransactionOutcome> commitMaybeRollback(TransactionCompletion trans)
Convenience method that creates and submits a endTransactionOperation
that commits by default but can be set to rollback by callingTransactionCompletion.setRollbackOnly()
. The endTransaction Operation is never skipped.- Parameters:
trans
- the TransactionCompletion that determines whether theOperation
is a database commit or a database rollback.- Returns:
- a
CompletionStage
that is completed with the outcome of the transaction - Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed or is parallel.
-
localOperation
<R extends S> LocalOperation<R> localOperation()
- Type Parameters:
R
- value type of the returned localOperation
- Returns:
- a LocalOperation
- Throws:
java.lang.IllegalStateException
- if thisOperationGroup
is closed.
-
logger
OperationGroup<S,T> logger(java.util.logging.Logger logger)
Supply aLogger
for the implementation of thisOperationGroup
to use to log significant events. Exactly what events are logged, at what Level the events are logged and with what parameters is implementation dependent. All memberOperation
s of thisOperationGroup
will use the sameLogger
except a memberOperationGroup
that is supplied with a differentLogger
uses thatLogger
. Supplying aLogger
configured with aMemoryHandler
with theMemoryHandler.pushLevel
set toLevel.WARNING
will result in no log output in normal operation. In the event of an error the actions leading up to the error will be logged. Implementation Note: Implementations are encouraged to log the creation of thisOperationGroup
set toLevel.INFO
, the creation of memberOperation
s at theLevel.CONFIG
level, and execution of memberOperation
s at theLevel.FINE
level. Detailed information about the execution of memberOperation
s may be logged at theLevel.FINER
andLevel.FINEST
levels. Errors in the execution of user code should be logged at theLevel.WARNING
Level. Errors in the implementation code should be logged at theLevel.SEVERE
Level.- Parameters:
logger
- used by the implementation to log significant events- Returns:
- this
OperationGroup
-
enquoteLiteral
default java.lang.String enquoteLiteral(java.lang.String val)
Returns aString
enclosed in single quotes. Any occurrence of a single quote within the string will be replaced by two single quotes.Examples of the conversion: Value Result Hello 'Hello' G'Day 'G''Day' 'G''Day' '''G''''Day''' I'''M 'I''''''M' - Parameters:
val
- a character string. Not null- Returns:
- A string enclosed by single quotes with every single quote converted to two single quotes. Not null
- Throws:
java.lang.NullPointerException
- ifval
isnull
java.lang.IllegalArgumentException
- ifval
cannot be enquoted- Implementation Note:
- ADBA driver implementations may need to provide their own implementation of this method in order to meet the requirements of the underlying datasource.
-
enquoteIdentifier
default java.lang.String enquoteIdentifier(java.lang.String identifier, boolean alwaysQuote)
Returns a SQL identifier. Ifidentifier
is a simple SQL identifier:- Return the original value if
alwaysQuote
isfalse
- Return a delimited identifier if
alwaysQuote
istrue
identifier
is not a simple SQL identifier,identifier
will be enclosed in double quotes if not already present. If the datasource does not support double quotes for delimited identifiers, the identifier should be enquoted by whatever mechanism the data source supports. If the datasource does not support delimited identifiers, anIllegalArgumentException
should be thrown.A
IllegalArgumentException
will be thrown ifidentifier
contains any characters invalid in a delimited identifier or the identifier length is invalid for the datasource.- Parameters:
identifier
- a SQL identifier. Not nullalwaysQuote
- indicates if a simple SQL identifier should be returned as a quoted identifier- Returns:
- A simple SQL identifier or a delimited identifier. Not null
- Throws:
java.lang.NullPointerException
- if identifier isnull
java.lang.IllegalArgumentException
- ifidentifier
can not be converted to a valid identifier- Implementation Requirements:
- The default implementation uses the following criteria to
determine a valid simple SQL identifier:
- The string is not enclosed in double quotes
- The first character is an alphabetic character from a through z, or from A through Z
- The name only contains alphanumeric characters or the character "_"
SQLException
if:identifier
contains anull
character or double quote and is not a simple SQL identifier.- The length of
identifier
is less than 1 or greater than 128 characters
Examples of the conversion: identifier alwaysQuote Result Hello false Hello Hello true "Hello" G'Day false "G'Day" "Bruce Wayne" false "Bruce Wayne" "Bruce Wayne" true "Bruce Wayne" GoodDay$ false "GoodDay$" Hello"World false IllegalArgumentException "Hello"World" false IllegalArgumentException - Implementation Note:
- ADBA driver implementations may need to provide their own implementation of this method in order to meet the requirements of the underlying datasource.
- Return the original value if
-
isSimpleIdentifier
default boolean isSimpleIdentifier(java.lang.String identifier)
Retrieves whetheridentifier
is a simple SQL identifier.- Parameters:
identifier
- a SQL identifier. Not null- Returns:
- true if a simple SQL identifier, false otherwise
- Throws:
java.lang.NullPointerException
- if identifier isnull
- Implementation Requirements:
- The default implementation uses the following criteria to
determine a valid simple SQL identifier:
- The string is not enclosed in double quotes
- The first character is an alphabetic character from a through z, or from A through Z
- The string only contains alphanumeric characters or the character "_"
- The string is between 1 and 128 characters in length inclusive
Examples of the conversion: identifier Simple Identifier Hello true G'Day false "Bruce Wayne" false GoodDay$ false Hello"World false "Hello"World" false - Implementation Note:
- ADBA driver implementations may need to provide their own implementation of this method in order to meet the requirements of the underlying datasource.
-
enquoteNCharLiteral
default java.lang.String enquoteNCharLiteral(java.lang.String val)
Returns aString
representing a National Character Set Literal enclosed in single quotes and prefixed with a upper case letter N. Any occurrence of a single quote within the string will be replaced by two single quotes.Examples of the conversion: Value Result Hello N'Hello' G'Day N'G''Day' 'G''Day' N'''G''''Day''' I'''M N'I''''''M' N'Hello' N'N''Hello''' - Parameters:
val
- a character string. Not null- Returns:
- the result of replacing every single quote character in the argument by two single quote characters where this entire result is then prefixed with 'N'. Not null.
- Throws:
java.lang.NullPointerException
- ifval
isnull
java.lang.IllegalArgumentException
- ifval
cannot be enquoted- Implementation Note:
- ADBA driver implementations may need to provide their own implementation of this method in order to meet the requirements of the underlying datasource. An implementation of enquoteNCharLiteral may accept a different set of characters than that accepted by the same drivers implementation of enquoteLiteral.
-
close
void close()
Allow thisOperationGroup
to be completed and removed from the queue once all of its memberOperation
s have been completed. After this method is called no additional memberOperation
s can be submitted. Once all memberOperation
s have been removed from the queue thisOperationGroup
will be completed and removed from the queue.- Specified by:
close
in interfacejava.lang.AutoCloseable
-
timeout
OperationGroup<S,T> timeout(java.time.Duration minTime)
The minimum time before thisOperation
might be canceled automatically. The default value is forever. The time is counted from the beginning of Operation execution. The Operation will not be canceled beforeminTime
after the beginning of execution. Some time at leastminTime
after the beginning of execution, an attempt will be made to cancel theOperation
if it has not yet completed. Implementations are encouraged to attempt to cancel within a reasonable time, though what is reasonable is implementation dependent.
-
onError
OperationGroup<S,T> onError(java.util.function.Consumer<java.lang.Throwable> handler)
Provides an error handler for thisOperation
. If execution of thisOperation
results in an error, before theOperation
is completed, the handler is called with theThrowable
as the argument. The type of theThrowable
is implementation dependent.
-
-