100 * remaining not-yet-executed members are completed exceptionally. If the |
100 * remaining not-yet-executed members are completed exceptionally. If the |
101 * {@link OperationGroup} is independent, the member {@link Operation}s are |
101 * {@link OperationGroup} is independent, the member {@link Operation}s are |
102 * executed regardless of whether one or more fails.</p> |
102 * executed regardless of whether one or more fails.</p> |
103 * |
103 * |
104 * <p> |
104 * <p> |
105 * A {@link Connection} is itself an {@link OperationGroup} and so can be |
105 * A single context in a data source is represented by a {@link Session}. A |
|
106 * {@link Session} is somewhat analogous to a logical {@link java.sql.Connection}. |
|
107 * A physical {@link java.sql.Connection} has no representation in this API; if |
|
108 * such an entity exists at all it is strictly internal to an implementation. |
|
109 * Within this spec this entity is referred to as a "data source resource". |
|
110 * </p> |
|
111 * |
|
112 * <p> |
|
113 * A {@link Session} is itself an {@link OperationGroup} and so can be |
106 * conditional, parallel, or independent, but by default is unconditional, |
114 * conditional, parallel, or independent, but by default is unconditional, |
107 * sequential, dependent. While a {@link Connection} may be created with values |
115 * sequential, dependent. While a {@link Session} may be created with values |
108 * other than the defaults, using the defaults is by far the most common case. |
116 * other than the defaults, using the defaults is by far the most common case. |
109 * The API provides convenience methods that support this case. Using these |
117 * The API provides convenience methods that support this case. Using these |
110 * convenience methods is recommended in all but the most unusual circumstances. |
118 * convenience methods is recommended in all but the most unusual circumstances. |
111 * In particular making the {@link Connection} parallel introduces some |
119 * In particular making the {@link Session} parallel introduces some |
112 * challenges that would require a full understanding of the details of the API. |
120 * challenges that would require a full understanding of the details of the API. |
113 * It would almost certainly be better to create a parallel |
121 * It would almost certainly be better to create a parallel |
114 * {@link OperationGroup} within the {@link Connection}.</p> |
122 * {@link OperationGroup} within the {@link Session}.</p> |
115 * |
123 * |
116 * <p> |
124 * <p> |
117 * <i> |
125 * <i> |
118 * ISSUE: Should we disallow {@code Connection.parallel()}?</i></p> |
126 * ISSUE: Should we disallow {@code Session.parallel()}?</i></p> |
119 * |
127 * |
120 * <p> |
128 * <p> |
121 * The {@code java.sql} API frequently provides many ways to do the same thing. |
129 * The {@code java.sql} API frequently provides many ways to do the same thing. |
122 * This API makes no attempt to do this. For those capabilities this API |
130 * This API makes no attempt to do this. For those capabilities this API |
123 * supports, it frequently defines exactly one way to do something. Doing things |
131 * supports, it frequently defines exactly one way to do something. Doing things |
185 * better that a feature be unsupported as opposed to users investing substantial |
193 * better that a feature be unsupported as opposed to users investing substantial |
186 * effort in an app using that feature only to discover in production that the |
194 * effort in an app using that feature only to discover in production that the |
187 * performance is unacceptable. For example, if an implementation can only support |
195 * performance is unacceptable. For example, if an implementation can only support |
188 * {@link Operation#timeout} through active polling it would be better for that |
196 * {@link Operation#timeout} through active polling it would be better for that |
189 * implementation to throw {@link UnsupportedOperationException} if |
197 * implementation to throw {@link UnsupportedOperationException} if |
190 * {@link Operation#timeout} is called.</p> |
198 * {@link Operation#timeout} is called. To this end every type and method is |
|
199 * optional except returning a {@link DataSourceFactory} in response to a call to |
|
200 * {@link DataSourceFactory#newFactory} with the appropriate name.</p> |
191 * |
201 * |
192 * <h3>Execution Model</h3> |
202 * <h3>Execution Model</h3> |
193 * |
203 * |
194 * <p> |
204 * <p> |
195 * <i>This section describes the function of a conforming implementation. It is |
205 * <i>This section describes the function of a conforming implementation. It is |
203 * |
213 * |
204 * <p> |
214 * <p> |
205 * An {@link Operation} is executed by causing the action to be performed, |
215 * An {@link Operation} is executed by causing the action to be performed, |
206 * processing the result of the action if there is a result processor, and |
216 * processing the result of the action if there is a result processor, and |
207 * completing the {@link java.util.concurrent.CompletionStage} with the result |
217 * completing the {@link java.util.concurrent.CompletionStage} with the result |
208 * of the result processor if there is one or with the result of the action if |
218 * of the result processor if there is one. If the action or the result processing |
209 * there is no result processor. If the action or the result processing causes |
219 * causes an unhandled error the {@link java.util.concurrent.CompletionStage} is |
210 * an unhandled error the {@link java.util.concurrent.CompletionStage} is |
|
211 * completed exceptionally. The {@link java.util.concurrent.CompletionStage} is |
220 * completed exceptionally. The {@link java.util.concurrent.CompletionStage} is |
212 * completed asynchronously, as though it were created by calling an |
221 * completed asynchronously, as though it were created by calling an |
213 * <i>async</i> method on {@link java.util.concurrent.CompletionStage}. |
222 * <i>async</i> method on {@link java.util.concurrent.CompletionStage}. |
214 * </p> |
223 * </p> |
215 * |
224 * |
216 * <p> |
225 * <p> |
217 * Performing the action may require one or more interactions with the database. |
226 * Performing the action may require one or more interactions with the database. |
218 * These interactions may be carried out in parallel with processing the result. |
227 * These interactions may be carried out in parallel with processing the result. |
219 * If the database result is ordered, that result is processed in that order. |
228 * If the database result is ordered, that result is processed in the order |
220 * |
229 * specified by the database.</p> |
221 * <p> |
230 * |
222 * An {@link OperationGroup} has a collection of {@link Operation}s and |
231 * <p> |
|
232 * An {@link OperationGroup} has a collection of member {@link Operation}s and |
223 * optionally a condition. For a sequential {@link OperationGroup} |
233 * optionally a condition. For a sequential {@link OperationGroup} |
224 * {@link Operation}s are selected from the collection in the order they were |
234 * {@link Operation}s are selected from the collection in the order they were |
225 * submitted. For a parallel {@link OperationGroup} {@link Operation}s are |
235 * submitted. For a parallel {@link OperationGroup} {@link Operation}s are |
226 * selected from the collection in any order.</p> |
236 * selected from the collection in any order.</p> |
227 * |
237 * |
253 * it may be completed exceptionally. The {@link OperationGroup} is dependent it |
263 * it may be completed exceptionally. The {@link OperationGroup} is dependent it |
254 * is completed exceptionally with the {@link Throwable} that caused the |
264 * is completed exceptionally with the {@link Throwable} that caused the |
255 * {@link Operation} to complete exceptionally. |
265 * {@link Operation} to complete exceptionally. |
256 * |
266 * |
257 * <p> |
267 * <p> |
258 * Note: the {@link Operation}s returned by {@link Connection#closeOperation} |
268 * Note: the {@link Operation}s returned by {@link Session#closeOperation} |
259 * and {@link OperationGroup#catchOperation} are never skipped, i.e. never |
269 * and {@link OperationGroup#catchOperation} are never skipped, i.e. never |
260 * completed exceptionally with {@link SqlSkippedException}. The {@link Operation} |
270 * completed exceptionally with {@link SqlSkippedException}. The {@link Operation} |
261 * returned by {@link OperationGroup#catchOperation} never completes |
271 * returned by {@link OperationGroup#catchOperation} never completes |
262 * exceptionally so the following {@link Operation} is always executed normally. |
272 * exceptionally so the following {@link Operation} is always executed normally. |
263 * No {@link Operation} can be submitted after the {@link Operation} returned by |
273 * No {@link Operation} can be submitted after the {@link Operation} returned by |
264 * {@link Connection#closeOperation} has been submitted.</p> </li> |
274 * {@link Session#closeOperation} has been submitted.</p> </li> |
265 * <li> |
275 * <li> |
266 * If the {@link OperationGroup} is independent and an {@link Operation} |
276 * If the {@link OperationGroup} is independent and an {@link Operation} |
267 * completes exceptionally all other {@link Operation}s are executed regardless. |
277 * completes exceptionally all other {@link Operation}s are executed regardless. |
268 * There is no result to be processed for an {@link Operation} that completed |
278 * There is no result to be processed for an {@link Operation} that completed |
269 * exceptionally. The {@link OperationGroup} is not completed exceptionally as |
279 * exceptionally. The {@link OperationGroup} is not completed exceptionally as |
270 * the result of one or more {@link Operation}s completing exceptionally.</li> |
280 * the result of one or more {@link Operation}s completing exceptionally.</li> |
271 * </ul> |
281 * </ul> |
272 * |
282 * |
273 * <p> |
283 * <p> |
274 * A {@link Connection} is a distinguished {@link OperationGroup}. A |
284 * A {@link Session} is a distinguished {@link OperationGroup}. A |
275 * {@link Connection} is executed upon being submitted.</p> |
285 * {@link Session} is executed upon being submitted.</p> |
276 * |
286 * |
277 * <h3>Transactions</h3> |
287 * <h3>Transactions</h3> |
278 * |
288 * |
279 * <p> |
289 * <p> |
280 * <i>This section describes the function of a conforming implementation. It is |
290 * <i>This section describes the function of a conforming implementation. It is |
291 * implementation in unexpected ways.</p> |
301 * implementation in unexpected ways.</p> |
292 * |
302 * |
293 * <p> |
303 * <p> |
294 * The creation of Operations and the subsequent execution of those Operations |
304 * The creation of Operations and the subsequent execution of those Operations |
295 * are separated in time. It is quite reasonable to determine that a transaction |
305 * are separated in time. It is quite reasonable to determine that a transaction |
296 * should commit after the Operation that ends the transaction is submitted. |
306 * should commit after the Operation that ends the transaction is submitted. But |
297 * But if the execution of the transaction does not result in the expected results |
307 * if the execution of the transaction does not result in the expected results |
298 * it might be necessary to rollback the transaction rather than commit it. This |
308 * it might be necessary to rollback the transaction rather than commit it. This |
299 * determination depends on the execution of the Operations long after the |
309 * determination depends on the execution of the Operations long after the |
300 * endTransaction Operation is created. To address this mismatch, the endTransaction Operation |
310 * endTransaction Operation is submitted. To address this mismatch, the |
301 * specified by this API is conditioned by a {@link Transaction}. By default, a |
311 * endTransaction Operation is conditioned by a {@link TransactionEnd}. By |
302 * {@link Transaction} will cause an endTransaciton {@link Operation} to commit |
312 * default, a {@link TransactionEnd} will cause an endTransaciton |
303 * the transaction. At any time before the endTransaction {@link Operation} that |
313 * {@link Operation} to commit the transaction. At any time before the |
304 * references it is executed a {@link Transaction} can be set |
314 * endTransaction {@link Operation} that references it is executed a |
305 * to rollback the transaction .</p> |
315 * {@link TransactionEnd} can be set to rollback the transaction .</p> |
306 * |
316 * |
307 * <p> |
317 * <p> |
308 * An endTransaction {@link Operation}, like all {@link Operation}s, is immutable once submitted. |
318 * An endTransaction {@link Operation}, like all {@link Operation}s, is |
309 * But an endTransaction {@link Operation} is created with a {@link Transaction} and that |
319 * immutable once submitted. But an endTransaction {@link Operation} is created |
310 * {@link Transaction} can be set to commit or rollback. A {@link Transaction} controls the |
320 * with a {@link TransactionEnd} and that {@link TransactionEnd} can be set to |
311 * endTransaction {@link Operation} created with it. Using this mechanism an |
321 * commit or rollback. A {@link TransactionEnd} controls the endTransaction |
312 * error handler, result handler or other code can cause a subsequent endTransaction |
322 * {@link Operation} created with it. Using this mechanism an error handler, |
|
323 * result handler or other code can cause a subsequent endTransaction |
313 * {@link Operation} to rollback instead of the default which is to commit.</p> |
324 * {@link Operation} to rollback instead of the default which is to commit.</p> |
314 * |
325 * |
315 * <pre> |
326 * <pre> |
316 * {@code |
327 * {@code |
317 * Transaction t = conn.getTransaction(); |
328 * TransactionEnd t = session.getTransactionEnd(); |
318 * conn.countOperation(updateSql) |
329 * session.countOperation(updateSql) |
319 * .resultProcessor( count -> { |
330 * .resultProcessor( count -> { |
320 * if (count > 1) t.setRollbackOnly(); |
331 * if (count > 1) t.setRollbackOnly(); |
321 * return null; |
332 * return null; |
322 * } ) |
333 * } ) |
323 * .submit(); |
334 * .submit(); |
324 * conn.catchErrors(); |
335 * session.catchErrors(); |
325 * conn.commitMaybeRollback(t); |
336 * session.commitMaybeRollback(t); |
326 * } |
337 * } |
327 * </pre> |
338 * </pre> |
328 * |
339 * |
329 * <p> |
340 * <p> |
330 * In this example if the update SQL modifies more than one row the result |
341 * In this example if the update SQL modifies more than one row the result |
331 * processor will set the Transaction to rollback only. When the endTransaction |
342 * processor will set the {@link TransactionEnd} to rollback only. When the |
332 * Operation submitted by commitMaybeRollback is executed it will cause |
343 * endTransaction {@link Operation} submitted by |
333 * the transaction to rollback.</p> |
344 * {@link OperationGroup#commitMaybeRollback} is executed it will cause the |
334 * |
345 * transaction to rollback.</p> |
|
346 * |
335 * |
347 * |
336 * <h3>Implementation Note</h3> |
348 * <h3>Implementation Note</h3> |
337 * |
349 * |
338 * <p> |
350 * <p> |
339 * If an implementation exposes any implementation specific types and methods, the |
351 * If an implementation exposes any implementation specific types and methods, the |
342 * |
354 * |
343 * <p> |
355 * <p> |
344 * Consider an implementation that adds a method foo() to RowCountOperation. To do |
356 * Consider an implementation that adds a method foo() to RowCountOperation. To do |
345 * that it would have to expose a type FooRowCountOperation extends RowCountOperation. |
357 * that it would have to expose a type FooRowCountOperation extends RowCountOperation. |
346 * So that an application can transparently access foo, the implementation would |
358 * So that an application can transparently access foo, the implementation would |
347 * also have to expose FooDataSource, FooOperationGroup and FooConnection. Further |
359 * also have to expose FooDataSource, FooOperationGroup and FooSession. Further |
348 * each of these types would have to declare covariant overrides for every method |
360 * each of these types would have to declare covariant overrides for every method |
349 * that returns a direct super-type of one of these types.</p> |
361 * that returns a direct super-type of one of these types.</p> |
350 * <ul> |
362 * <ul> |
351 * <li>FooDataSourceFactory must override builder to return FooDataSource.Builder</li> |
363 * <li>FooDataSourceFactory must override builder to return FooDataSource.Builder</li> |
352 * <li>FooDataSource.Builder must override url, password, etc to return a |
364 * <li>FooDataSource.Builder must override url, password, etc to return a |
353 * FooDataSource.Builder. build must return a FooDataSource.</li> |
365 * FooDataSource.Builder. build must return a FooDataSource.</li> |
354 * <li>FooDataSource must override builder to return FooConnection.Builder</li> |
366 * <li>FooDataSource must override builder to return FooSession.Builder</li> |
355 * <li>FooConnection.Builder must override url, password, etc to return a |
367 * <li>FooSession.Builder must override url, password, etc to return a |
356 * FooConnection.Builder. build must return a FooConnection</li> |
368 * FooSession.Builder. build must return a FooSession</li> |
357 * <li>FooDataSource must override getConnection to return FooConnection</li> |
369 * <li>FooDataSource must override getSession to return FooSession</li> |
358 * <li>FooConnection must extend FooOperationGroup</li> |
370 * <li>FooSession must extend FooOperationGroup</li> |
359 * <li>FooOperationGroup> must override rowCountOperation to return FooRowCountOperation</li> |
371 * <li>FooOperationGroup> must override rowCountOperation to return FooRowCountOperation</li> |
360 * <li>FooRowCountOperation must override apply and onError to return FooRowCountOperation</li> |
372 * <li>FooRowCountOperation must override apply and onError to return FooRowCountOperation</li> |
361 * </ul> |
373 * </ul> |
362 * <p> |
374 * <p> |
363 * The intent is to transparently expose the vendor extension without use of casts. |
375 * The intent is to transparently expose the vendor extension without use of casts. |
367 * {@code |
379 * {@code |
368 * FooDataSourceFactory factory = DataSourceFatory.newFactory("com.foo.FooDataSourceFatory"); |
380 * FooDataSourceFactory factory = DataSourceFatory.newFactory("com.foo.FooDataSourceFatory"); |
369 * FooDataSource dataSource = factory.builder() |
381 * FooDataSource dataSource = factory.builder() |
370 * .url("scott/tiger@host:port") |
382 * .url("scott/tiger@host:port") |
371 * .build(); |
383 * .build(); |
372 * FooConnection conn = dataSource.getConnection(); |
384 * FooSession session = dataSource.getSession(); |
373 * CompletionStage<Long> count = conn.rowOperation(sql) |
385 * CompletionStage<Long> count = session.rowOperation(sql) |
374 * .set("param", value, AdbaType.VARCHAR) |
386 * .set("param", value, AdbaType.VARCHAR) |
375 * .foo() |
387 * .foo() |
376 * .submit() |
388 * .submit() |
377 * .getCompletionStage(); |
389 * .getCompletionStage(); |
378 * } |
390 * } |