56380
|
1 |
/*
|
56475
|
2 |
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
56380
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation. Oracle designates this
|
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
|
9 |
* by Oracle in the LICENSE file that accompanied this code.
|
|
10 |
*
|
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
15 |
* accompanied this code).
|
|
16 |
*
|
|
17 |
* You should have received a copy of the GNU General Public License version
|
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20 |
*
|
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
22 |
* or visit www.oracle.com if you need additional information or have any
|
|
23 |
* questions.
|
|
24 |
*/
|
|
25 |
|
|
26 |
|
|
27 |
/**
|
|
28 |
* <p>
|
|
29 |
* An API for accessing and processing data stored in a data source (usually a
|
|
30 |
* relational database) using the Java™ programming language. This API
|
|
31 |
* includes a framework whereby different drivers can be installed dynamically
|
|
32 |
* to access different data sources. This API is specifically geared for passing
|
|
33 |
* SQL statements to a database though it may be used for reading and writing
|
|
34 |
* data from/to any data source that has a tabular format.</p>
|
|
35 |
*
|
|
36 |
* <p>
|
|
37 |
* This API differs from the API in {@code java.sql} in several ways.</p>
|
|
38 |
* <ul>
|
|
39 |
* <li>Is asynchronous
|
|
40 |
* <li>Is geared toward high-throughput programs
|
|
41 |
* <li>Does not attempt to support every database feature
|
|
42 |
* <li>Does not attempt to abstract the database
|
|
43 |
* <li>Uses the builder pattern
|
|
44 |
* <li>Supports the fluent programming style
|
|
45 |
* </ul>
|
|
46 |
*
|
|
47 |
* <p>
|
|
48 |
* It is worth emphasizing that this API is an alternate to the {@code java.sql}
|
|
49 |
* API, not a replacement. There are many programs that can much more readily be
|
|
50 |
* written using the {@code java.sql} API as it has many features that are not
|
|
51 |
* available in this API. For example this API provides almost no mechanism for
|
|
52 |
* getting metadata.</p>
|
|
53 |
*
|
|
54 |
* <p>
|
|
55 |
* This API is not an extension to the {@code java.sql} API. It an independent
|
|
56 |
* API and is used on its own without reference to java.sql. </p>
|
|
57 |
*
|
|
58 |
*
|
|
59 |
* <h3>Overview</h3>
|
|
60 |
*
|
|
61 |
* <p>
|
|
62 |
* The core feature of this API is that it is asynchronous. No method call will
|
|
63 |
* wait for a network operation. </p>
|
|
64 |
*
|
|
65 |
* <p>
|
|
66 |
* Possibly blocking actions are represented as {@link Operation}s. An
|
|
67 |
* application using the API creates and submits one or more {@link Operation}s.
|
56475
|
68 |
* The implementation executes these {@link Operation}s asynchronously, reporting
|
|
69 |
* their results via {@link java.util.concurrent.CompletionStage}s. An application
|
56380
|
70 |
* can respond to the results via the
|
|
71 |
* {@link java.util.concurrent.CompletionStage}s or via callbacks that can be
|
|
72 |
* configured on many of the {@link Operation}s or both. Creating and submitting
|
|
73 |
* {@link Operation}s is strictly non-blocking. Handling the results of possibly
|
|
74 |
* blocking {@link Operation}s is done asynchronously. No application thread
|
|
75 |
* will ever block on a call to a method in this API.</p>
|
|
76 |
*
|
|
77 |
* <p>
|
|
78 |
* All {@link Operation}s provide a
|
|
79 |
* {@link java.util.concurrent.CompletionStage}. The value of that
|
|
80 |
* {@link java.util.concurrent.CompletionStage} is the value of the
|
|
81 |
* {@link Operation}, set when the {@link Operation} completes. Some
|
|
82 |
* {@link Operation}s provide callbacks for processing the result of the
|
|
83 |
* {@link Operation} independent of the
|
|
84 |
* {@link java.util.concurrent.CompletionStage}. Those {@link Operation}s can
|
|
85 |
* be used for executing SQL that returns results of a specific type. For
|
|
86 |
* example SQL that returns a row sequence would be executed with a
|
|
87 |
* {@link RowOperation}. A {@link RowOperation} provides callbacks for
|
|
88 |
* processing each row and for collecting the results of processing the rows.
|
|
89 |
* Other {@link Operation}s are specialized for SQL that returns a count or that
|
|
90 |
* returns out parameters. The choice of {@link Operation} is dependent on the
|
|
91 |
* result to be processed and is independent of the particular kind of SQL
|
|
92 |
* statement.</p>
|
|
93 |
*
|
|
94 |
* <p>
|
|
95 |
* An {@link OperationGroup} encapsulates a group of {@link Operation}s and
|
|
96 |
* executes them using common attributes. An {@link OperationGroup} can be
|
|
97 |
* unconditional or conditional, sequential or parallel, dependent or
|
|
98 |
* independent, or any combination of these. Dependent/independent controls
|
|
99 |
* error handling. If one member of a dependent {@link OperationGroup} fails the
|
|
100 |
* remaining not-yet-executed members are completed exceptionally. If the
|
|
101 |
* {@link OperationGroup} is independent, the member {@link Operation}s are
|
|
102 |
* executed regardless of whether one or more fails.</p>
|
|
103 |
*
|
|
104 |
* <p>
|
56824
|
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
|
56380
|
114 |
* conditional, parallel, or independent, but by default is unconditional,
|
56824
|
115 |
* sequential, dependent. While a {@link Session} may be created with values
|
56380
|
116 |
* other than the defaults, using the defaults is by far the most common case.
|
|
117 |
* The API provides convenience methods that support this case. Using these
|
|
118 |
* convenience methods is recommended in all but the most unusual circumstances.
|
56824
|
119 |
* In particular making the {@link Session} parallel introduces some
|
56380
|
120 |
* challenges that would require a full understanding of the details of the API.
|
|
121 |
* It would almost certainly be better to create a parallel
|
56824
|
122 |
* {@link OperationGroup} within the {@link Session}.</p>
|
56380
|
123 |
*
|
|
124 |
* <p>
|
|
125 |
* <i>
|
56824
|
126 |
* ISSUE: Should we disallow {@code Session.parallel()}?</i></p>
|
56380
|
127 |
*
|
|
128 |
* <p>
|
|
129 |
* The {@code java.sql} API frequently provides many ways to do the same thing.
|
|
130 |
* This API makes no attempt to do this. For those capabilities this API
|
|
131 |
* supports, it frequently defines exactly one way to do something. Doing things
|
|
132 |
* another way, for example calling methods in a non-standard order, frequently
|
|
133 |
* results in an IllegalStateException. This approach is intended to make things
|
|
134 |
* simpler for both the user and the implementor. Rather than having to
|
|
135 |
* understand complicated interactions of many different components and methods
|
|
136 |
* executed in any order, the intent is that there is only one way to do things
|
|
137 |
* so only one path must be understood or implemented. Anything off that path is
|
|
138 |
* an error. While this requires a programmer to write code in one specific way
|
|
139 |
* it makes things easier on future maintainers of the code as the code will
|
|
140 |
* conform to the standard pattern. Similarly the implementation is simplified
|
|
141 |
* as only the standard use pattern is supported.</p>
|
|
142 |
*
|
|
143 |
* <p>
|
|
144 |
* One way this API simplifies things in to define types as single use. Many
|
56475
|
145 |
* types are created, configured, used once, and are then no longer usable. Most
|
56380
|
146 |
* configuration methods can be called only once on a given instance. Once an
|
|
147 |
* instance is configured it cannot be reconfigured. Once an instance is used it
|
|
148 |
* cannot be reused. This simplifies things by eliminating the need to
|
|
149 |
* understand and implement arbitrary sequences of method calls that reconfigure
|
|
150 |
* and reuse instances. Since objects are single use there is no expectation
|
|
151 |
* that an application cache or share {@link Operation}s.</p>
|
|
152 |
*
|
|
153 |
* <p>
|
|
154 |
* While the user visible types are single use, it is expected that an
|
|
155 |
* implementation will cache and reuse data and {@link Object}s that are worth
|
|
156 |
* the effort. Rather than attempt to guess what an implementation should reuse
|
|
157 |
* and capture that in the API, this API leaves it entirely up to the
|
|
158 |
* implementation. Since the API specifies very little reuse, an implementation
|
|
159 |
* is free to reuse whatever is appropriate. Since the pattern of use is
|
|
160 |
* strictly enforced figuring out how to reuse objects is greatly
|
|
161 |
* simplified.</p>
|
|
162 |
*
|
|
163 |
* <p>
|
|
164 |
* The {@code java.sql} API provides many tools for abstracting the database,
|
|
165 |
* for enabling the user to write database independent code. This API does not.
|
|
166 |
* It is not a goal of this API to enable users to write database independent
|
|
167 |
* code. That is not to say it is not possible, just that this API does not
|
|
168 |
* provide tools to support such. Abstraction features typically impose
|
|
169 |
* performance penalties on some implementations. As this API is geared for
|
|
170 |
* high-throughput programs it avoids such abstractions rather than reduce
|
|
171 |
* performance.</p>
|
|
172 |
*
|
|
173 |
* <p>
|
|
174 |
* One such abstraction feature is the JDBC escape sequences. Implementing these
|
|
175 |
* features requires parsing the SQL so as to identify the escape sequences and
|
|
176 |
* then generating a new String with the vendor specific SQL corresponding to
|
|
177 |
* the escape sequence. This is an expensive operation. Further each SQL must be
|
|
178 |
* parsed whether it contains an escape sequence or not imposing the cost on all
|
|
179 |
* JDBC users, not just the ones who use escape sequences. The same is true of
|
|
180 |
* JDBC parameter markers. The SQL accepted by this API is entirely vendor
|
|
181 |
* specific, including parameter markers. There is no need for pre-processing
|
|
182 |
* prior to SQL execution substantially reducing the amount of work the
|
|
183 |
* implementation must do.</p>
|
|
184 |
*
|
|
185 |
* <p>
|
|
186 |
* Note: It would be a reasonable future project to develop a SQL builder API
|
|
187 |
* that creates vendor specific SQL from some more abstract representation.</p>
|
56475
|
188 |
*
|
|
189 |
* <p>
|
|
190 |
* This API is targeted at high-throughput apps. If a particular feature of this
|
|
191 |
* API would have a surprising performance impact for a particular implementation
|
|
192 |
* it is recommended that the implementation not implement that feature. It is
|
|
193 |
* better that a feature be unsupported as opposed to users investing substantial
|
|
194 |
* effort in an app using that feature only to discover in production that the
|
|
195 |
* performance is unacceptable. For example, if an implementation can only support
|
|
196 |
* {@link Operation#timeout} through active polling it would be better for that
|
56797
|
197 |
* implementation to throw {@link UnsupportedOperationException} if
|
56824
|
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>
|
56380
|
201 |
*
|
|
202 |
* <h3>Execution Model</h3>
|
|
203 |
*
|
|
204 |
* <p>
|
|
205 |
* <i>This section describes the function of a conforming implementation. It is
|
|
206 |
* not necessary for an implementation to be implemented as described only that
|
|
207 |
* the behavior be the same.</i></p>
|
|
208 |
*
|
|
209 |
* <p>
|
|
210 |
* An {@link Operation} has an action and a
|
|
211 |
* {@link java.util.concurrent.CompletionStage}. Some {@link Operation}s have
|
|
212 |
* some form of result processor.</p>
|
|
213 |
*
|
|
214 |
* <p>
|
|
215 |
* An {@link Operation} is executed by causing the action to be performed,
|
|
216 |
* processing the result of the action if there is a result processor, and
|
|
217 |
* completing the {@link java.util.concurrent.CompletionStage} with the result
|
56824
|
218 |
* of the result processor if there is one. If the action or the result processing
|
|
219 |
* causes an unhandled error the {@link java.util.concurrent.CompletionStage} is
|
56797
|
220 |
* completed exceptionally. The {@link java.util.concurrent.CompletionStage} is
|
|
221 |
* completed asynchronously, as though it were created by calling an
|
|
222 |
* <i>async</i> method on {@link java.util.concurrent.CompletionStage}.
|
56380
|
223 |
* </p>
|
|
224 |
*
|
|
225 |
* <p>
|
|
226 |
* Performing the action may require one or more interactions with the database.
|
|
227 |
* These interactions may be carried out in parallel with processing the result.
|
56824
|
228 |
* If the database result is ordered, that result is processed in the order
|
|
229 |
* specified by the database.</p>
|
56380
|
230 |
*
|
|
231 |
* <p>
|
56824
|
232 |
* An {@link OperationGroup} has a collection of member {@link Operation}s and
|
56380
|
233 |
* optionally a condition. For a sequential {@link OperationGroup}
|
|
234 |
* {@link Operation}s are selected from the collection in the order they were
|
|
235 |
* submitted. For a parallel {@link OperationGroup} {@link Operation}s are
|
|
236 |
* selected from the collection in any order.</p>
|
|
237 |
*
|
|
238 |
* <p>
|
|
239 |
* The action of an {@link OperationGroup} is performed as follows:
|
|
240 |
* <ul>
|
|
241 |
* <li>
|
|
242 |
* If the {@link OperationGroup} has a condition, the value of the condition is
|
|
243 |
* retrieved. If the value is {@link Boolean#FALSE} the action is complete and
|
|
244 |
* the {@link java.util.concurrent.CompletionStage} is completed with null. If
|
56797
|
245 |
* the condition value completes exceptionally the action is complete and the
|
56380
|
246 |
* {@link java.util.concurrent.CompletionStage} is completed exceptionally
|
|
247 |
* with the same exception. If the condition value is {@link Boolean#TRUE} or
|
|
248 |
* there is no condition the {@link Operation}s in the collection are executed
|
|
249 |
* and their results processed. The action is complete when the
|
|
250 |
* {@link OperationGroup} is not held and all the {@link Operation}s have been
|
|
251 |
* executed.</li>
|
|
252 |
* <li>
|
56797
|
253 |
* If the {@link OperationGroup} is parallel more than one member
|
|
254 |
* {@link Operation} may be executed at a time.</li>
|
56380
|
255 |
* <li>
|
56797
|
256 |
* If the {@link OperationGroup} is dependent and a member {@link Operation} completes
|
|
257 |
* exceptionally all member {@link Operation}s that are yet to begin
|
56380
|
258 |
* execution are completed exceptionally with a {@link SqlSkippedException}. The
|
|
259 |
* cause of that exception is the {@link Throwable} that caused the
|
|
260 |
* {@link Operation} to be completed exceptionally. If an {@link Operation} is
|
|
261 |
* in flight when another {@link Operation} completes exceptionally the in
|
|
262 |
* flight {@link Operation} may either be allowed to complete uninterrupted or
|
56797
|
263 |
* it may be completed exceptionally. The {@link OperationGroup} is dependent it
|
|
264 |
* is completed exceptionally with the {@link Throwable} that caused the
|
|
265 |
* {@link Operation} to complete exceptionally.
|
56475
|
266 |
*
|
|
267 |
* <p>
|
56824
|
268 |
* Note: the {@link Operation}s returned by {@link Session#closeOperation}
|
56479
|
269 |
* and {@link OperationGroup#catchOperation} are never skipped, i.e. never
|
56475
|
270 |
* completed exceptionally with {@link SqlSkippedException}. The {@link Operation}
|
|
271 |
* returned by {@link OperationGroup#catchOperation} never completes
|
56797
|
272 |
* exceptionally so the following {@link Operation} is always executed normally.
|
56475
|
273 |
* No {@link Operation} can be submitted after the {@link Operation} returned by
|
56824
|
274 |
* {@link Session#closeOperation} has been submitted.</p> </li>
|
56380
|
275 |
* <li>
|
|
276 |
* If the {@link OperationGroup} is independent and an {@link Operation}
|
|
277 |
* completes exceptionally all other {@link Operation}s are executed regardless.
|
|
278 |
* There is no result to be processed for an {@link Operation} that completed
|
|
279 |
* exceptionally. The {@link OperationGroup} is not completed exceptionally as
|
|
280 |
* the result of one or more {@link Operation}s completing exceptionally.</li>
|
|
281 |
* </ul>
|
|
282 |
*
|
|
283 |
* <p>
|
56824
|
284 |
* A {@link Session} is a distinguished {@link OperationGroup}. A
|
|
285 |
* {@link Session} is executed upon being submitted.</p>
|
56380
|
286 |
*
|
|
287 |
* <h3>Transactions</h3>
|
|
288 |
*
|
|
289 |
* <p>
|
|
290 |
* <i>This section describes the function of a conforming implementation. It is
|
|
291 |
* not necessary for an implementation to be implemented as described only that
|
|
292 |
* the behavior be the same.</i></p>
|
|
293 |
*
|
|
294 |
* <p>
|
|
295 |
* An implementation has only limited control over transactions. SQL statements
|
|
296 |
* can start, commit, and rollback transactions without the implementation
|
|
297 |
* having any influence or even being aware. This specification only describes
|
|
298 |
* the behavior of those transaction actions that are visible to and controlled
|
|
299 |
* by the implementation, i.e. the endTransaction {@link Operation}.
|
|
300 |
* Transaction actions caused by SQL may interact with actions controlled by the
|
|
301 |
* implementation in unexpected ways.</p>
|
|
302 |
*
|
|
303 |
* <p>
|
|
304 |
* The creation of Operations and the subsequent execution of those Operations
|
|
305 |
* are separated in time. It is quite reasonable to determine that a transaction
|
56824
|
306 |
* should commit after the Operation that ends the transaction is submitted. But
|
|
307 |
* if the execution of the transaction does not result in the expected results
|
56380
|
308 |
* it might be necessary to rollback the transaction rather than commit it. This
|
|
309 |
* determination depends on the execution of the Operations long after the
|
56824
|
310 |
* endTransaction Operation is submitted. To address this mismatch, the
|
|
311 |
* endTransaction Operation is conditioned by a {@link TransactionEnd}. By
|
|
312 |
* default, a {@link TransactionEnd} will cause an endTransaciton
|
|
313 |
* {@link Operation} to commit the transaction. At any time before the
|
|
314 |
* endTransaction {@link Operation} that references it is executed a
|
|
315 |
* {@link TransactionEnd} can be set to rollback the transaction .</p>
|
56380
|
316 |
*
|
|
317 |
* <p>
|
56824
|
318 |
* An endTransaction {@link Operation}, like all {@link Operation}s, is
|
|
319 |
* immutable once submitted. But an endTransaction {@link Operation} is created
|
|
320 |
* with a {@link TransactionEnd} and that {@link TransactionEnd} can be set to
|
|
321 |
* commit or rollback. A {@link TransactionEnd} controls the endTransaction
|
|
322 |
* {@link Operation} created with it. Using this mechanism an error handler,
|
|
323 |
* result handler or other code can cause a subsequent endTransaction
|
56475
|
324 |
* {@link Operation} to rollback instead of the default which is to commit.</p>
|
56380
|
325 |
*
|
|
326 |
* <pre>
|
|
327 |
* {@code
|
56824
|
328 |
* TransactionEnd t = session.getTransactionEnd();
|
|
329 |
* session.countOperation(updateSql)
|
56380
|
330 |
* .resultProcessor( count -> {
|
|
331 |
* if (count > 1) t.setRollbackOnly();
|
|
332 |
* return null;
|
|
333 |
* } )
|
|
334 |
* .submit();
|
56824
|
335 |
* session.catchErrors();
|
|
336 |
* session.commitMaybeRollback(t);
|
56380
|
337 |
* }
|
|
338 |
* </pre>
|
|
339 |
*
|
|
340 |
* <p>
|
|
341 |
* In this example if the update SQL modifies more than one row the result
|
56824
|
342 |
* processor will set the {@link TransactionEnd} to rollback only. When the
|
|
343 |
* endTransaction {@link Operation} submitted by
|
|
344 |
* {@link OperationGroup#commitMaybeRollback} is executed it will cause the
|
|
345 |
* transaction to rollback.</p>
|
|
346 |
*
|
56380
|
347 |
*
|
56797
|
348 |
* <h3>Implementation Note</h3>
|
|
349 |
*
|
|
350 |
* <p>
|
|
351 |
* If an implementation exposes any implementation specific types and methods, the
|
|
352 |
* implementation is expected to provide covariant overrides for all methods that
|
|
353 |
* return the standard super-type of the implementation specific type.</p>
|
|
354 |
*
|
|
355 |
* <p>
|
|
356 |
* Consider an implementation that adds a method foo() to RowCountOperation. To do
|
|
357 |
* that it would have to expose a type FooRowCountOperation extends RowCountOperation.
|
|
358 |
* So that an application can transparently access foo, the implementation would
|
56824
|
359 |
* also have to expose FooDataSource, FooOperationGroup and FooSession. Further
|
56797
|
360 |
* each of these types would have to declare covariant overrides for every method
|
|
361 |
* that returns a direct super-type of one of these types.</p>
|
|
362 |
* <ul>
|
|
363 |
* <li>FooDataSourceFactory must override builder to return FooDataSource.Builder</li>
|
|
364 |
* <li>FooDataSource.Builder must override url, password, etc to return a
|
|
365 |
* FooDataSource.Builder. build must return a FooDataSource.</li>
|
56824
|
366 |
* <li>FooDataSource must override builder to return FooSession.Builder</li>
|
|
367 |
* <li>FooSession.Builder must override url, password, etc to return a
|
|
368 |
* FooSession.Builder. build must return a FooSession</li>
|
|
369 |
* <li>FooDataSource must override getSession to return FooSession</li>
|
|
370 |
* <li>FooSession must extend FooOperationGroup</li>
|
56797
|
371 |
* <li>FooOperationGroup> must override rowCountOperation to return FooRowCountOperation</li>
|
|
372 |
* <li>FooRowCountOperation must override apply and onError to return FooRowCountOperation</li>
|
|
373 |
* </ul>
|
|
374 |
* <p>
|
|
375 |
* The intent is to transparently expose the vendor extension without use of casts.
|
|
376 |
* Example: </p>
|
|
377 |
*
|
|
378 |
* <pre>
|
|
379 |
* {@code
|
|
380 |
* FooDataSourceFactory factory = DataSourceFatory.newFactory("com.foo.FooDataSourceFatory");
|
|
381 |
* FooDataSource dataSource = factory.builder()
|
|
382 |
* .url("scott/tiger@host:port")
|
|
383 |
* .build();
|
56824
|
384 |
* FooSession session = dataSource.getSession();
|
|
385 |
* CompletionStage<Long> count = session.rowOperation(sql)
|
56797
|
386 |
* .set("param", value, AdbaType.VARCHAR)
|
|
387 |
* .foo()
|
|
388 |
* .submit()
|
|
389 |
* .getCompletionStage();
|
|
390 |
* }
|
|
391 |
* </pre>
|
|
392 |
*
|
|
393 |
* <p>
|
|
394 |
* Notice that there are no casts, yet both standard methods an the vendor extension
|
|
395 |
* method foo can be referenced. This is possible only if the implementation exposes
|
|
396 |
* all the necessary types and provides covariant overrides for every method that
|
|
397 |
* returns one of those types. Implementations are expected (required?) to do this.
|
|
398 |
* </p>
|
|
399 |
*
|
|
400 |
* <p>
|
|
401 |
* If an implementation does not expose any implementation specific methods or
|
|
402 |
* types, that implementation is not required to provide covariant overrides that
|
|
403 |
* return implementation specific types.</p>
|
|
404 |
*
|
|
405 |
*
|
56380
|
406 |
*/
|
56475
|
407 |
package jdk.incubator.sql2;
|
56479
|
408 |
|