Skip to content

Commit 57e57af

Browse files
Merge pull request #43 from oracle/0_3_0_update
0.3.0 updates
2 parents 7f3e9c3 + dd8c5a8 commit 57e57af

File tree

12 files changed

+331
-191
lines changed

12 files changed

+331
-191
lines changed

README.md

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ Oracle R2DBC implements the R2DBC Service Provider Interface (SPI) as specified
88
### Learn More About R2DBC:
99
[R2DBC Project Home Page](https://r2dbc.io)
1010

11-
[R2DBC Javadocs v0.9.0.M1](https://r2dbc.io/spec/0.9.0.M1/api/)
11+
[R2DBC Javadocs v0.9.0.M2](https://r2dbc.io/spec/0.9.0.M2/api/)
1212

13-
[R2DBC Specification v0.9.0.M1](https://r2dbc.io/spec/0.9.0.M1/spec/html/)
13+
[R2DBC Specification v0.9.0.M2](https://r2dbc.io/spec/0.9.0.M2/spec/html/)
1414

1515
### Learn More About Reactive Streams:
1616
[Reactive Streams Project Home Page](http://www.reactive-streams.org)
@@ -19,14 +19,26 @@ Oracle R2DBC implements the R2DBC Service Provider Interface (SPI) as specified
1919

2020
[Reactive Streams Specification v1.0.3](https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.3/README.md)
2121
# About This Version
22-
Oracle R2DBC 0.2.0 updates the implemented SPI version to 0.9.0.M1. With the
23-
0.9.0.M1 SPI update, Oracle R2DBC 0.2.0 introduces support for procedural
24-
calls (PL/SQL), the ```Statement.bind(...)``` methods are enhanced to accept
25-
```io.r2dbc.spi.Parameter``` objects, and the
26-
```Connection.beginTransaction(TransactionDefintion)``` method is
27-
implemented to support named and read-only/read-write transactions.
28-
29-
# Performance Goals
22+
The 0.3.0 release Oracle R2DBC implements version 0.9.0.M2 of the R2DBC SPI.
23+
The 0.9.0.M2 SPI update introduces support for consuming a `Result` as a
24+
stream of `Segment` objects, configuring statement execution timeouts, and
25+
managing pooled `Connection`s with the `LifeCycle` interface.
26+
27+
The 0.3.0 release updates the Oracle JDBC dependency to 21.3. The 21.3 release
28+
introduces several improvements for the Reactive Extensions:
29+
- Substantial reduction in object allocation costs.
30+
- Row mapping functions will no longer contend with other threads for
31+
access to the JDBC connection.
32+
- Blocking database calls are no longer required for PreparedStatements
33+
returning values generated by DML.
34+
35+
### Spring Integration
36+
Use the 0.1.0 version of Oracle R2DBC if you are programming with Spring.
37+
The later versions of Oracle R2DBC implement the 0.9.x versions of the R2DBC
38+
SPI. Currently, Spring only supports drivers that implement the 0.8.x versions
39+
of the SPI.
40+
41+
### Performance Goals
3042
The primary goal of these early releases of Oracle R2DBC is to support the R2DBC
3143
SPI on Oracle Database. The only performance goal is to enable concurrent
3244
database calls to be executed by a single thread.
@@ -48,18 +60,20 @@ Artifacts can also be found on Maven Central.
4860
<dependency>
4961
<groupId>com.oracle.database.r2dbc</groupId>
5062
<artifactId>oracle-r2dbc</artifactId>
51-
<version>${version}</version>
63+
<version>0.3.0</version>
5264
</dependency>
5365
```
5466

5567
Oracle R2DBC is compatible with JDK 11 (or newer), and has the following runtime dependencies:
56-
- R2DBC SPI 0.9.0.M1
68+
- R2DBC SPI 0.9.0.M2
5769
- Reactive Streams 1.0.3
58-
- Project Reactor 3.0.0
59-
- Oracle JDBC 21.1.0.0 for JDK 11 (ojdbc11.jar)
60-
- Oracle R2DBC relies on the Oracle JDBC Driver's [Reactive Extensions](https://docs.oracle.com/en/database/oracle/oracle-database/21/jjdbc/jdbc-reactive-extensions.html#GUID-1C40C43B-3823-4848-8B5A-D2F97A82F79B) APIs. These APIs were introduced in the 21.1 release of Oracle JDBC, and are only available with the JDK 11 build (ojdbc11).
70+
- Project Reactor 3.3.0.RELEASE
71+
- Oracle JDBC 21.3.0.0 for JDK 11 (ojdbc11.jar)
72+
- Oracle R2DBC relies on the Oracle JDBC Driver's [Reactive Extensions
73+
](https://docs.oracle.com/en/database/oracle/oracle-database/21/jjdbc/jdbc-reactive-extensions.html#GUID-1C40C43B-3823-4848-8B5A-D2F97A82F79B) APIs.
6174

62-
The Oracle R2DBC Driver has been verified with Oracle Database versions 19c and 21c.
75+
The Oracle R2DBC Driver has been verified with Oracle Database versions 18, 19,
76+
and 21.
6377

6478
# Code Examples
6579

@@ -74,7 +88,7 @@ Mono.from(connectionFactory.create())
7488
"SELECT 'Hello, Oracle' FROM sys.dual")
7589
.execute())
7690
.flatMap(result ->
77-
result.map((row, metadata) -> row.get(0, String.class)))
91+
result.map(row -> row.get(0, String.class)))
7892
.doOnNext(System.out::println)
7993
.thenMany(connection.close()))
8094
.subscribe();
@@ -90,7 +104,7 @@ Mono.from(connectionFactory.create())
90104
.bind("locale_name", "France")
91105
.execute())
92106
.flatMap(result ->
93-
result.map((row, metadata) ->
107+
result.map(row ->
94108
String.format("%s, Oracle", row.get("greeting", String.class))))
95109
.doOnNext(System.out::println)
96110
.thenMany(connection.close()))
@@ -128,8 +142,8 @@ This document specifies the behavior of the R2DBC SPI implemented for the
128142
Oracle Database. This SPI implementation is referred to as the "Oracle R2DBC
129143
Driver" or "Oracle R2DBC" throughout the remainder of this document.
130144

131-
The Oracle R2DBC Driver implements behavior specified by the R2DBC 0.9.0.M1
132-
[Specification](https://r2dbc.io/spec/0.9.0.M1/spec/html/)
145+
The Oracle R2DBC Driver implements behavior specified by the R2DBC 0.9.0.M2
146+
[Specification](https://r2dbc.io/spec/0.9.0.M2/spec/html/)
133147
and [Javadoc](https://r2dbc.io/spec/0.8.3.RELEASE/api/)
134148

135149
Publisher objects created by Oracle R2DBC implement behavior specified by
@@ -146,8 +160,8 @@ implements a ConnectionFactoryProvider located by an R2DBC URL identifing
146160
"oracle" as a driver, or by a DRIVER ConnectionFactoryOption with the value
147161
of "oracle".
148162
- The following well-known ConnectionFactory Options are supported:
149-
DRIVER, USER, PASSWORD, HOST, PORT, DATABASE, SSL, and
150-
CONNECT_TIMEOUT.
163+
DRIVER, USER, PASSWORD, HOST, PORT, DATABASE, SSL,
164+
CONNECT_TIMEOUT, STATEMENT_TIMEOUT.
151165
- The DATABASE ConnectionFactoryOption is interpreted as the
152166
[service name](https://docs.oracle.com/en/database/oracle/oracle-database/21/netag/identifying-and-accessing-database.html#GUID-153861C1-16AD-41EC-A179-074146B722E6) of an Oracle Database instance.
153167
System Identifiers (SID) are not recognized.
@@ -175,7 +189,7 @@ Options. For Options having any of the following names, a CharSequence value may
175189
- [oracle.jdbc.implicitStatementCacheSize](https://docs.oracle.com/en/database/oracle/oracle-database/21/jajdb/oracle/jdbc/OracleConnection.html?is-external=true#CONNECTION_PROPERTY_IMPLICIT_STATEMENT_CACHE_SIZE)
176190
- [oracle.jdbc.defaultLobPrefetchSize](https://docs.oracle.com/en/database/oracle/oracle-database/21/jajdb/oracle/jdbc/OracleConnection.html?is-external=true#CONNECTION_PROPERTY_DEFAULT_LOB_PREFETCH_SIZE)
177191
- [oracle.net.disableOob](https://docs.oracle.com/en/database/oracle/oracle-database/21/jajdb/oracle/jdbc/OracleConnection.html?is-external=true#CONNECTION_PROPERTY_THIN_NET_DISABLE_OUT_OF_BAND_BREAK)
178-
- Out of band (oob) breaks effect statement timeouts. Set this to "true"
192+
- Out of band (OOB) breaks effect statement timeouts. Set this to "true"
179193
if statement timeouts are not working correctly.
180194
- Oracle Net Descriptors of the form ```(DESCRIPTION=...)``` may be specified as an io.r2dbc.spi.Option having the name `oracleNetDescriptor`.
181195
- If `oracleNetDescriptor` is specified, then it is invalid to specify any other options that might conflict with information in the descriptor, such as: `HOST`, `PORT`, `DATABASE`, and `SSL`.
@@ -210,8 +224,9 @@ or Oracle JDBC Driver error message](https://docs.oracle.com/en/database/oracle/
210224
- READ COMMITTED is the default transaction isolation level, and is the
211225
only level supported in this release.
212226
- Transaction savepoints are not supported in this release.
213-
- TransactionDefinition.LOCK_WAIT_TIMEOUT is not supported in this release.
214-
- Oracle Database does not support a lock wait timeout that applies to all statements within a transaction.
227+
- Oracle Database does not support a lock wait timeout that is configurable
228+
within the scope of a transaction or session. SPI methods that configure a
229+
lock wait timeout throw ```UnsupportedOperationException```
215230

216231
### Statements
217232
- Batch execution is only supported for DML type SQL commands (INSERT/UPDATE/DELETE).
@@ -229,12 +244,6 @@ of each row affected by an INSERT or UPDATE.
229244
- The ROWID of a row may change.
230245
- After a row is deleted, its ROWID may be reassigned to a new row.
231246
- Further Reading: https://asktom.oracle.com/pls/apex/asktom.search?tag=is-it-safe-to-use-rowid-to-locate-a-row
232-
- A **blocking database call** is executed by a Statement returning generated
233-
values for a non-empty set of column names.
234-
- The **blocking database call** is a known limitation that will be resolved
235-
with a non-blocking implementation of
236-
java.sql.Connection.prepareStatement(String, String[]) in the Oracle JDBC Driver.
237-
The Oracle JDBC Team is aware of this problem and is working on a fix.
238247
- Returning generated values is only supported for INSERT and UPDATE commands when a RETURNING INTO clause can be appended to the end of that command. (This limitation may be resolved in a later release)
239248
- Example: `INSERT INTO my_table(val) VALUES (:val)` is supported because a RETURNING INTO clause may be appended to this command.
240249
- Example: `INSERT INTO my_table(val) SELECT 1 FROM sys.dual` is not supported because a RETURNING INTO clause may not be appended to this command.
@@ -260,9 +269,9 @@ values for a non-empty set of column names.
260269
```io.r2dbc.spi.Parameter.Out``` and
261270
```io.r2dbc.spi.Parameter.In``` marker interfaces.
262271
- Consume out parameters by invoking
263-
```Result.map(BiFunction<Row, RowMetadata>)```:
272+
```Result.map(Function)```:
264273
```java
265-
result.map((row,metadata) -> row.get("greeting_out", String.class))
274+
result.map(outParameters -> outParameters.get("greeting_out", String.class))
266275
```
267276
- ```Statement.execute()``` returns a ```Publisher<Result>``` that emits one
268277
```Result``` for each cursor returned by ```DBMS_SQL.RETURN_RESULT```

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
<groupId>com.oracle.database.r2dbc</groupId>
2828
<artifactId>oracle-r2dbc</artifactId>
29-
<version>0.2.0</version>
29+
<version>0.3.0</version>
3030
<name>oracle-r2dbc</name>
3131
<description>
3232
Oracle R2DBC Driver implementing version 0.9.0.M2 of the R2DBC SPI for Oracle Database.
@@ -65,7 +65,7 @@
6565

6666
<properties>
6767
<java.version>11</java.version>
68-
<ojdbc.version>21.1.0.0</ojdbc.version>
68+
<ojdbc.version>21.3.0.0</ojdbc.version>
6969
<r2dbc.version>0.9.0.M2</r2dbc.version>
7070
<reactor.version>3.3.0.RELEASE</reactor.version>
7171
<reactive-streams.version>1.0.3</reactive-streams.version>

src/main/java/module-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
with oracle.r2dbc.impl.OracleConnectionFactoryProviderImpl;
3131

3232
requires java.sql;
33-
requires ojdbc11;
33+
requires com.oracle.database.jdbc;
3434
requires reactor.core;
3535
requires transitive org.reactivestreams;
3636
requires transitive r2dbc.spi;

src/main/java/oracle/r2dbc/impl/OracleConnectionFactoryImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,23 @@ final class OracleConnectionFactoryImpl implements ConnectionFactory {
175175
OracleR2dbcExceptions.requireNonNull(options, "options is null.");
176176
adapter = ReactiveJdbcAdapter.getOracleAdapter();
177177
dataSource = adapter.createDataSource(options);
178+
179+
// Handle any Options that Oracle JDBC doesn't
180+
if (options.hasOption(ConnectionFactoryOptions.LOCK_WAIT_TIMEOUT)) {
181+
throw new UnsupportedOperationException(
182+
"Unsupported Option: "
183+
+ ConnectionFactoryOptions.LOCK_WAIT_TIMEOUT.name()
184+
+ ". Oracle Database does not support a lock wait timeout session " +
185+
"parameter.");
186+
}
187+
178188
statementTimeout = Optional.ofNullable(
179189
options.getValue(ConnectionFactoryOptions.STATEMENT_TIMEOUT))
180190
.map(timeout -> (timeout instanceof Duration)
181191
? (Duration)timeout
182192
: Duration.parse(timeout.toString()))
183193
.orElse(Duration.ZERO);
194+
184195
}
185196

186197
/**

src/main/java/oracle/r2dbc/impl/OracleResultImpl.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,16 @@ static OracleResultImpl createUpdateCountResult(long updateCount) {
356356
return new UpdateCountResult(updateCount);
357357
}
358358

359+
/**
360+
* Creates a {@code Result} that publishes a batch of {@code updateCounts}
361+
* as {@link UpdateCount} segments
362+
* @return A {@code Result} for a batch DML update
363+
* @param updateCounts Update counts to publish
364+
*/
365+
static OracleResultImpl createBatchUpdateResult(long[] updateCounts) {
366+
return new BatchUpdateResult(updateCounts);
367+
}
368+
359369
/**
360370
* Creates a {@code Result} that publishes update counts of a
361371
* {@code batchUpdateException} as {@link UpdateCount} segments, followed a
@@ -444,18 +454,17 @@ <T> Publisher<T> publishSegments(Function<Segment, T> mappingFunction) {
444454
private static final class ResultSetResult extends OracleResultImpl {
445455

446456
private final ResultSet resultSet;
457+
private final RowMetadataImpl metadata;
447458
private final ReactiveJdbcAdapter adapter;
448459

449460
private ResultSetResult(ResultSet resultSet, ReactiveJdbcAdapter adapter) {
450461
this.resultSet = resultSet;
462+
this.metadata = createRowMetadata(fromJdbc(resultSet::getMetaData));
451463
this.adapter = adapter;
452464
}
453465

454466
@Override
455467
<T> Publisher<T> publishSegments(Function<Segment, T> mappingFunction) {
456-
RowMetadataImpl metadata =
457-
createRowMetadata(fromJdbc(resultSet::getMetaData));
458-
459468
return adapter.publishRows(resultSet, jdbcReadable ->
460469
mappingFunction.apply(
461470
new RowSegmentImpl(createRow(jdbcReadable, metadata, adapter))));
@@ -595,7 +604,9 @@ <T> Publisher<T> publishSegments(Function<Segment, T> mappingFunction) {
595604
// Invoke publishSegments(Class, Function) rather than
596605
// publishSegments(Function) to update the state of the result; Namely,
597606
// the state that has the onConsumed Publisher emit a terminal signal.
598-
.concatWith(result.publishSegments(Segment.class, mappingFunction));
607+
.concatWith(result != null
608+
? result.publishSegments(Segment.class,mappingFunction)
609+
: Mono.empty());
599610
}
600611
}
601612

0 commit comments

Comments
 (0)